跟踪java堆而不使用本机代码

时间:2013-12-27 06:13:38

标签: java assembly bytecode

我正在摆弄Java堆一段时间。使用JVMTI,我们可以跟踪java堆。

但有没有办法用纯java实现相同的目标?

我在运行时使用java instrumentation和asm框架进行类转换。

我的目标是跟踪创建的每个对象,这意味着我需要定期检查它们的大小。我可以检查是否使用asm创建了新对象。我需要的是检查从堆空间创建的对象的大小。

这方面有什么指示?

于2013年12月28日编辑

好的,我能够从ASM做一些事情虽然它可能不是最好的解决方案(我完全同意的最佳方式是JVMTI。)

我必须覆盖visitVarInsn(对于局部变量),visitFieldInsn(例如和类变量)和visitTypeInsn(对于NEWNEWARRAY对象得到创造)

每次创建一个新对象时,我都会记录该对象(是的,这不是我知道的好方法,这可能会导致资源泄漏。如果你有更好的解决方案,请告诉我。我需要它太糟糕了 [:(]) 我会定期检查对象大小。

你能为我提供更好的选择吗? (正如史蒂芬正确地指出的那样,这个对象记录肯定不会起作用,但我对JVMTI [[((])感到不舒服。另外,原谅我的无知,我找不到合适的{{1方法。

MemoryMXBeanMXBean,但我无法通过此方法跟踪单个对象的大小。也许我应该写自己的getHeapMemoryUsage()

3 个答案:

答案 0 :(得分:3)

我想你可以在理论上做到这一点。对象的(浅)大小很容易根据对象字段的数量和类型来计算,并且您可以使用ASM工具将代码插入到每个构造函数中,以便在每次构造对象时记录大小(某处)。

处理数组会很棘手。数组分配不需要构造函数,因此您需要检测创建数组的所有位置。由于其中一些地方可能使用本机代码,因此很难看出如何执行此操作。

另一个棘手的案例是处理创建对象而不调用其构造函数的事物;例如对象序列化和本机克隆。

总而言之,这可能不是一个实用的方法。


另一点是,任何使用ASM和类似内容的东西都可以 而不是“纯Java”......除非用法实际上是JVM本身的一部分。

答案 1 :(得分:1)

由于您正在使用Instrumentation,因此您已经可以访问告诉您对象大小的API。用于修改类的字节代码的Instrumentation类提供方法getObjectSize(Object)

您提及的有关对象跟踪的资源泄漏可以轻松解决。只需将对象放入WeakReference s。然后,您可以使用ReferenceQueue来了解对象何时被垃圾回收,这是您想要跟踪堆使用情况时的一项重要功能。

但我不太确定你想要达到的目标。

顺便说一下,据我所知,JVisualVM 使用JVMTI。但是JVisualVM也不会跟踪每个对象。完整堆分析需要堆转储。这可以使用MXBean with the name "com.sun.management:type=HotSpotDiagnostic"发送方法调用dumpHeap(String outputFile, boolean live)来完成。

答案 2 :(得分:0)

使用Runtime

    long MEGABYTE = 1024L * 1024L;
    Runtime runtime = Runtime.getRuntime();
    runtime.gc();
    System.out.println("Total Memory : " + runtime.totalMemory()/MEGABYTE);
    System.out.println("Used Memory  : " + (runtime.totalMemory() - runtime.freeMemory()) / MEGABYTE);
    System.out.println("Free Memory  : " + runtime.freeMemory() / MEGABYTE);