java - Java 内存泄漏:为什么不收集无法访问的对象?
问题描述
我正在尝试为 JDK Nashorn 错误JDK-8229011找到解决方法。
我使用错误票证中链接的脚本重现了该错误,并进行了几次堆转储。我使用 JProfiler 和 Eclipse Memory Analyzer 来找到问题的根源。但是,我总是以无法到达的路径告终,我不明白为什么对象没有被垃圾收集。AFAIS 没有终结器可以让它们保持活力。如果我在 JProfiler 中打开堆转储而不禁用“Full GC on Dump”,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
我正在寻找一些提示,是什么让这些物体保持活力。
解决方案
我不知道发生了什么,但是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
组件报告还说:
弱参考统计
一共找到了10007个java.lang.ref.WeakReference对象,其中弱引用了6969个对象。总共 192 B 的 6 个对象仅通过弱引用被保留(保持活动状态)。可能的内存泄漏 总计 124.4 KB 的 5,785 个对象被弱引用,并且还通过弱引用强保留(保持活动状态)。
细节 ”
推荐阅读
- vue.js - 如何修复 Vue 3 + Vue 路由器 4 中的“未定义 Vue”?
- c# - 错误 NETSDK1060:读取资产文件时出错:无法加载文件或程序集
- postgresql - Postgres 2 节点集群设置
- python - python中国际象棋引擎的Minimax函数无法解包不可迭代的NoneType对象
- aws-lambda - Lambda node.js 运行时中的“异步处理程序”和“非异步处理程序”之间有什么区别吗?
- javascript - 如何使用带有 select: 滚动的 addEvent 创建事件?
- rust - vec 内可变大小切片上的非消耗可变迭代器
- ssl - 让我们加密、Cloudflare 和通配符 SSL
- r - 在R中将日期转换为小时
- typescript - 在 ArrayLike 组上链接泛型