如何进一步利用eclipse MAT挖掘这个内存泄漏

时间:2012-11-18 15:12:44

标签: eclipse eclipse-mat mat

我遇到一个问题,其中ScheduledThreadPoolExecutor最终会有300万个未来任务。我试图看看什么类型的任务,所以我可以去任务的安排,但我不知道如何从这个屏幕获取任何信息(我已经尝试右键单击这些未来的任务,并在菜单中选择各种选项) 。似乎gui中缺少某些东西,比如指向实际的runnables或其他东西......

关于如何深入研究的任何想法?

enter image description here

1 个答案:

答案 0 :(得分:2)

一些通用的东西

你需要知道,如果你有一个可移植的堆转储(phd,see types here),那么它不包含实际的数据(基元),那么你只能根据参考图制作你的发现(哪些类型包含对其他类型的引用。)

您可以尝试OQL。这是一种类似SQL的语言,您可以使用它来查询对象。

一个例子:

select * from java.lang.String s where s.@retainedHeapSize>10000

这会返回所有字符串,大于~10k。 你也可以制作一些函数(比如这里aggregating)。

你可以尝试一下。

至于当前的问题

如果你检查FutureTask源代码(这里是JDK6):

public class FutureTask<V> implements RunnableFuture<V> {
    /** Synchronization control for FutureTask */
    private final Sync sync;

...
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }
...

    public FutureTask(Runnable runnable, V result) {
        sync = new Sync(Executors.callable(runnable, result));
    }

实际的Runnable由Sync对象引用:

  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<V> 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<V> callable) {
            this.callable = callable;
        }

因此在GUI中打开Sync对象(未在图片中打开),然后您可以检查Runnables。

我不知道你是否可以更改代码,但通常最好总是限制执行程序使用的队列大小,因为这样可以避免泄漏。或者您可以使用一些持久队列。如果您应用限制,则可以定义拒绝策略,例如拒绝,在调用者中运行等。有关详细信息,请参阅http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html