 <h2>Some General Stuff</h2> <p>You need to know, that if you have a portable heap dump (phd, <a href="http://memoryanalyzer.blogspot.co.at/2010/01/heap-dump-analysis-with-memory-analyzer.html" rel="nofollow">see types here</a>), then it does not contain actual data (primitives), so then you can make your findings only based on reference map (which types hold a reference to which other types).</p> <p>You can give a try to <a href="http://help.eclipse.org/indigo/index.jsp?topic=/org.eclipse.mat.ui.help/reference/oqlsyntax.html" rel="nofollow">OQL</a>. This is an SQL like language, with which you can query your objects.</p> <p>One example:</p> <pre><code>select * from java.lang.String s where s.@retainedHeapSize&gt;10000 </code></pre> <p>This gives back all strings, that are bigger than ~10k. You can make also some functions (like this <a href="http://stackoverflow.com/a/9469829/337621">aggregating</a> here).</p> <p>You could give a try to it.</p> <h2>As for the current problem</h2> <p>If you check the FutureTask source (here is JDK6 below):</p> <pre><code>public class FutureTask&lt;V&gt; implements RunnableFuture&lt;V&gt; { /** Synchronization control for FutureTask */ private final Sync sync; ... public FutureTask(Callable&lt;V&gt; callable) { if (callable == null) throw new NullPointerException(); sync = new Sync(callable); } ... public FutureTask(Runnable runnable, V result) { sync = new Sync(Executors.callable(runnable, result)); } </code></pre> <p>The actual Runnable is referred by the Sync object:</p> <pre><code> private final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -7828117401763700385L; /** State value representing that task is running */ private static final int RUNNING = 1; /** State value representing that task ran */ private static final int RAN = 2; /** State value representing that task was cancelled */ private static final int CANCELLED = 4; /** The underlying callable */ private final Callable&lt;V&gt; callable; /** The result to return from get() */ private V result; /** The exception to throw from get() */ private Throwable exception; /** * The thread running task. When nulled after set/cancel, this * indicates that the results are accessible. Must be * volatile, to ensure visibility upon completion. */ private volatile Thread runner; Sync(Callable&lt;V&gt; callable) { this.callable = callable; } </code></pre> <p>So in the GUI open the Sync object (not open in your picture), and then you can check the Runnables.</p> <p>I dont know if you can change the code or not, but in general it is better always limit the size of the queue used by an executor, since this way you can avoid leaks. Or you can use some persisted queue. If you apply a limit you can define the rejection policy like for example reject, run in caller and so on. See <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html" rel="nofollow">http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html</a> for details.</p>