如何阅读 Eclipse 内存分析器的 "Merge Shortest Paths to GC Roots" 屏幕?

How to read "Merge Shortest Paths to GC Roots" screen of Eclipse Memory Analyzer?

我正在努力解决这个问题

java.lang.OutOfMemoryError: Metaspace

在 运行 网络应用程序(Apache Roller,Java EE weblogger 软件:https://roller.apache.org)在 Tomcat 8.0.18 上重新部署时。

我知道问题的原因可以通过 Eclipse 内存分析器找到,所以我在 OOME 时得到了一个堆转储,它是由 运行

的 JVM 自动生成的
-XX:+HeapDumpOnOutOfMemoryError.

我可以看到应该对 4 个 WebappClassLoader 实例进行垃圾回收。但我不确定为什么这些实例没有被垃圾收集。

所以这是我在 Merge Shortest Paths to GC Roots => exclude all phantom/weak/soft/etc. references 屏幕中针对每个 WebappClassLoader 个实例的问题:

  1. 这是否意味着 PostgreSQL JDBC 驱动程序(部署在服务器端)引用了 RollerContext?

  2. 这看起来像 SoftEntryReference 的实例引用了 WebappClassLoader,但我猜它不是强引用,所以它不会阻止 [=14] =] 被垃圾收集。我错了吗?

  3. 我不知道这是什么意思...这是什么意思? WebappClassLoader 本身是否可以防止被垃圾收集?

  4. 就像我在 2 中写的那样,我猜它应该被垃圾收集,因为它被 SoftReference 引用。我错了吗?

Does this mean PostgreSQL JDBC Driver (deployed on the server side) has a reference to RollerContext?

是的,看起来是这样。特别是通过静态变量中保存的异常对象的回溯。

Merge Shortest Paths to GC Roots => exclude all phantom/weak/soft/etc. references

[...]

This looks like a instance of SoftEntryReference has a reference to WebappClassLoader, but I guess it is not a strong reference

[...]

Like I wrote in 2, I guess it should be garbage collected because it's referenced by a SoftReference. Am I wrong?

你错了。

就垃圾收集器而言,您没有查看软引用。软引用对象中只有一个字段不强,那就是 referent 字段。

查看 JDK 的 java.lang.ref.Reference<T> class 内部,您会看到还有其他字段。您还会注意到 SoftReference 是 subclassable,因此可以有额外的字段。所有非引用字段都是强引用。

MAT 表示您正在查看的内容由 discovered 字段链保存,这意味着引用对象肯定保持活动状态,即使它们的引用对象可能已被回收。

I have no idea what this means... What does this mean? Does WebappClassLoader itself prevents to be garbage collected?

这在 eclipse docs 中有解释:它是一个 GC 根,因为该对象持有锁,并且它当前由本机代码处理,例如JNI.

这是 "eclipse mat busy monitor" 的第一个 google 结果。请做你的研究。