Java内存泄漏:为什么不收集无法访问的对象?

时间:2020-06-26 11:35:49

标签: java memory-leaks out-of-memory nashorn eclipse-memory-analyzer

我正在尝试找到针对JDK Nashorn错误JDK-8229011的解决方法。

我用错误票证中链接的脚本重现了错误,并进行了几次堆转储。我使用了JProfiler和Eclipse Memory Analyzer 找到问题的根源。但是,我总是以无法到达的路径结束,而且我不明白为什么不对这些对象进行垃圾收集。 AFAIS没有终结器可以使它们存活。 如果我在JProfiler中打开堆转储而不禁用“ Dump上的完整GC”,JProfiler甚至会丢弃无法访问的对象。但是GC本身不会。我使用G1 GC进行了测试,但是使用CMS进行了测试。

通过使用以下设置运行以下脚本,您可以在1-2分钟内使用任何JDK> 8进行示例转储:-Xmx20M -XX:+HeapDumpOnOutOfMemoryError

public class TestJsMemLeak
{
    public static final class JsJavaUtil
    {
        private long counter = 0;

        public long testFunc()
        {
            return counter++;
        }
    }

    public static void main(final String[] args) throws Exception
    {
        System.setProperty("nashorn.args", "--no-java -doe -ot=false --language=es6 --no-deprecation-warning --lazy-compilation=false");       
        for (long i = 0; true; ++i)
        {
            final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
            scriptEngine.put("JsJavaUtil", new JsJavaUtil());
            scriptEngine.eval("for (var i = 0; i < 10; ++i) {\n" + " JsJavaUtil.testFunc();\n" + "}");
            System.gc();
            if (i % 100 == 0)
            {
                System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
            }
        }
    }
}

运行此操作将导致转储,其中包含约6-7 MB的java.lang.ClassValue $ ClassValueMap无法访问

我正在寻找一些提示,是什么使这些对象保持活动状态。

1 个答案:

答案 0 :(得分:0)

我不知道发生了什么,但是latest development build of Eclipse Memory Analyzer给出了一些有趣的发现。 快照比较-加载堆转储1,加载堆转储2,运行 “快照比较可疑 :包括泄漏嫌疑人 和比较两个快照的系统概述。”

问题嫌疑人1

由“”加载的“ java.lang.ClassValue $ ClassValueMap”的一个实例占用+809,280(19.48%)字节。内存存储在一个由“”加载的“ java.lang.ClassValue $ ClassValueMap”实例中,该实例占用+809,280(19.48%)字节。

关键字 java.lang.ClassValue $ ClassValueMap

“组件”报告也显示:

参考统计不足

总共找到了10,007个java.lang.ref.WeakReference对象,其中几乎引用了6,969个对象。 总共192 B的6个对象仅通过弱引用保留(保留)。 可能会泄漏5785个对象,总计124.4 KB,可能会被弱引用,并且也会通过弱引用强烈保留(保持活动状态)。

详细信息»