Java 如何阅读;“将最短路径合并到GC根”;Eclipse内存分析器的屏幕?

Java 如何阅读;“将最短路径合并到GC根”;Eclipse内存分析器的屏幕?,java,tomcat,memory-leaks,garbage-collection,classloader,Java,Tomcat,Memory Leaks,Garbage Collection,Classloader,我正在努力解决这个问题 java.lang.OutOfMemoryError: Metaspace 在重新部署时,在Tomcat8.0.18上运行web应用程序(ApacheRoller,JavaEEWeblogger软件:) 我知道问题的原因可以通过Eclipse内存分析器找到,所以我在OOME时得到了一个堆转储,它是由运行的JVM自动生成的 -XX:+HeapDumpOnOutOfMemoryError. 我可以看到有4个WebappClassLoader实例应该被垃圾收集。但我不确定为

我正在努力解决这个问题

java.lang.OutOfMemoryError: Metaspace
在重新部署时,在Tomcat8.0.18上运行web应用程序(ApacheRoller,JavaEEWeblogger软件:)

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

-XX:+HeapDumpOnOutOfMemoryError.
我可以看到有4个WebappClassLoader实例应该被垃圾收集。但我不确定为什么这些实例没有被垃圾收集。

下面是我在
Merge Shortest path to GC root=>排除所有幻影/弱/软/等中的问题。每个
WebappClassLoader
实例的参考
屏幕:

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

  • 这看起来像是
    SoftEntryReference
    的一个实例引用了
    WebappClassLoader
    ,但我猜它不是一个强引用,因此它不会阻止
    WebappClassLoader
    被垃圾收集。我错了吗?

  • 我不知道这意味着什么。。。这是什么意思?
    WebappClassLoader
    本身是否阻止垃圾收集?

  • 就像我在2中写的,我想它应该被垃圾收集,因为它被一个软引用引用。我错了吗?

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

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

    将最短路径合并到GC根=>排除所有虚/弱/软/等引用

    [……]

    这看起来像是SoftEntryReference的一个实例引用了WebappClassLoader,但我猜它不是一个强引用

    [……]

    就像我在2中写的,我想它应该被垃圾收集,因为它被一个软引用引用。我错了吗

    你错了

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

    查看JDK的
    java.lang.ref.Reference
    类,您将看到还有其他字段。您还将注意到,
    SoftReference
    是子类的,因此可以有额外的字段。所有非引用字段都是强引用

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

    我不知道这意味着什么。。。这是什么意思?WebappClassLoader本身是否阻止垃圾收集

    这在中进行了解释:它是一个GC根,因为该对象上有一个锁,并且它当前由本机代码(例如JNI)处理

    这是第一个谷歌搜索结果。请做你的研究

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

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

    将最短路径合并到GC根=>排除所有虚/弱/软/等引用

    [……]

    这看起来像是SoftEntryReference的一个实例引用了WebappClassLoader,但我猜它不是一个强引用

    [……]

    就像我在2中写的,我想它应该被垃圾收集,因为它被一个软引用引用。我错了吗

    你错了

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

    查看JDK的
    java.lang.ref.Reference
    类,您将看到还有其他字段。您还将注意到,
    SoftReference
    是子类的,因此可以有额外的字段。所有非引用字段都是强引用

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

    我不知道这意味着什么。。。这是什么意思?WebappClassLoader本身是否阻止垃圾收集

    这在中进行了解释:它是一个GC根,因为该对象上有一个锁,并且它当前由本机代码(例如JNI)处理


    这是第一个谷歌搜索结果。请进行研究。

    至于1,现在我怀疑这是JDBC驱动程序的一个bug,所以我向pgsql JDBC邮件列表报告了它:。至于其他问题,我通过你的精彩解释理解了,但仍然不知道是什么导致了这些强有力的参考或繁忙的监控。您怎么看呢?4是由线程局部变量(记录器调度程序线程)保持活动的。用一个新线程替换该线程可以解决这个问题,关闭其线程池也可以解决这个问题。其中一个类加载器可能是最新的,即应该是活动的。如果软引用被未耗尽的引用队列使用,则软引用可能会延迟。您可能需要在根的最短路径之外探索对象图,以查看这些对象属于什么。也就是说,最短路径可能只是巧合/暂时的,而到GC根的其他路径可以使其长期保持活动状态。作为最后手段,始终可以选择使用反射来挖掘引用,并消除那些麻烦的引用。但是,当您在其中进行反射的库发生更改时,这很容易出错,也很脆弱。现在我猜这可能与Google Guice的一个问题有关,当它与web应用(例如)一起部署时,会导致类加载器泄漏。如果我能进一步调查的话,我会报告的。至于1,我现在怀疑