【问题标题】:A way to get all objects instances from JVM memory一种从 JVM 内存中获取所有对象实例的方法
【发布时间】:2020-08-10 13:22:11
【问题描述】:

有没有办法从 JVM 内存中获取所有对象实例并在文件中打印其 toString() 表示?

我需要在出现错误时拍摄我的应用的所有对象实例。

我认为转储不是我要寻找的,因为它没有给我关于目前内存中包含哪些实例的准确信息,只有静态信息。

【问题讨论】:

  • 这将为您解决什么问题?
  • 你在问如何进行堆转储吗?
  • @NomadMaker 我需要记录远程用户在出错时刻的系统使用信息,所以我需要类似于 IDE 在调试模式下提供的信息。
  • @andy-turner 堆转储是否提供有关对象实例的信息 - 它们的全局变量和出错时方法中的局部变量?

标签: java memory jvm


【解决方案1】:

您所要求的本质上称为堆转储。

Heapdump 是给定时间内 JVM 内存的快照,它包含有关所有对象的信息。

要捕获它,您可以这样做

jmap -dump:format=b,file=heap.bin <pid>
  • pid:Java 进程的 ID

有几种工具可以分析输出的文件。好的变化是您的 IDE 可以做到,这样您就可以在熟悉的界面中查看它。

这里有更多 https://dzone.com/articles/java-heap-dump-analyzer-1

要以编程方式触发 hepdump,您可以执行以下操作

public class HeapDumper {
    
    private static final String HOTSPOT_BEAN_NAME =
        "com.sun.management:type=HotSpotDiagnostic";
    private static volatile HotSpotDiagnosticMXBean hotspotMBean;

    static void dumpHeap(String fileName, boolean live) {
        initHotspotMBean();
        try {
            hotspotMBean.dumpHeap(fileName, live);
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    private static void initHotspotMBean() {
        if (hotspotMBean == null) {
            synchronized (HeapDumper.class) {
                if (hotspotMBean == null) {
                    hotspotMBean = getHotspotMBean();
                }
            }
        }
    }
    
    private static HotSpotDiagnosticMXBean getHotspotMBean() {
        try {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            HotSpotDiagnosticMXBean bean =
                ManagementFactory.newPlatformMXBeanProxy(server,
                                                         HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
            return bean;
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }
}

这样触发


String fileName = "heap.bin";
boolean live = true; // only reachable object - true, all objects - false
dumpHeap(fileName, live);

【讨论】:

  • 感谢您的回答!我可以通过 Java 代码访问 JMAP 吗?
  • 添加了解释如何手动触发的代码。你的用例是什么?在我 10 年的编程生涯中,我只需要这个一次。也许你做的有些过头了。
  • 不错的答案!我也想知道用例。
  • 再次感谢您。我为 Java 应用程序开发了一个记录器模块。应用程序是具有其他一些功能的解析器。它会产生各种错误,因此需要记录有关它的信息,包括错误时的堆转储。包含有关对象实例的信息的堆转储可以提供有关错误时刻正在处理的实体的有用信息。此用例是否有一些更好的做法?
  • 堆转储不是一种廉价或快速的操作。因此,请考虑错误会导致更多问题的严重程度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2017-07-05
  • 1970-01-01
  • 2011-01-03
  • 2015-03-06
  • 1970-01-01
相关资源
最近更新 更多