【问题标题】:How can we know whether an object is marked as garbage by GC?我们如何知道一个对象是否被 GC 标记为垃圾?
【发布时间】:2021-12-16 21:25:25
【问题描述】:

是否有任何工具可以可视化特定对象上的 GC 状态?

【问题讨论】:

    标签: java garbage-collection jvm


    【解决方案1】:

    简短的回答是没有好的方法。

    并且没有任何方法可以在不会(以各种方式)改变您尝试检查的对象的行为的程序中执行此操作。

    “不好”的方法是:

    • 通过使用Reference 类型。问题是这会改变对象的生命周期,并且只会告诉您对象在 GC 运行的最后一个时间点的状态。

    • 通过获取堆转储并使用堆转储分析器对其进行检查。问题是进行堆转储是一个代价高昂的“停止世界”事件,它使用大量磁盘空间并且需要大量 RAM 来加载和分析转储。

    最后,您可能不会通过这样做学到很多东西,除非您正在搜索可疑的内存泄漏。

    【讨论】:

    • 有什么好的堆转储工具吗?我只是想对此做一个小实验。
    • 尝试使用 visualvm 分析堆转储。
    【解决方案2】:

    如果您可以访问该对象,那么它通常是不可收集的。

    JVMTI 系统(Java 虚拟机工具接口)允许其他进程连接到 JVM 并从中获取统计信息。这是调试器和分析器使用的; visualvm(大多数 JDK 附带)可以做到这一点,许多商业产品也可以。它们为您提供了一些 GC 见解。

    JDK 本身也可以这样做,更多信息请使用 -XX:+PrintGCDetails - read this article

    在同一个 JVM 中,您可以使用 java.lang.ref 中的类来引用对象,而不会妨碍垃圾回收。琐碎:

    class Test {
      private final WeakReference<String> weakRef;
    
      public void test() {
        String y = new String("");
        weakRef = new WeakReference<>(y);
      }
    
      public boolean hasItBeenCollectedYet() {
        // weak refs don't impede collection; `.get()` returns null once
        // the object begins its collection process.
        return weakRef.get() == null;
      }
    }
    

    但是,使用该系统只是收集一般统计数据?这不是很好 - 其他两个选项要好得多。

    【讨论】:

    • 请注意,weakRef.get() == null 如果对象尚未被收集,则临时将强对象引用放在堆栈上,如果并发收集器此时检查正确(或看到一些标志告诉该对象已在 GC 周期期间被访问)。从 JDK 16 开始,您可以使用 weakRef.refersTo(null) 来检查这一点,而无需收到强引用。另一种方法是使用ReferenceQueue 并检查weakRef 是否已入队。
    猜你喜欢
    • 2011-07-16
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多