我正在摆弄Java堆一段时间。使用JVMTI
,我们可以跟踪java堆。
但有没有办法用纯java实现相同的目标?
我在运行时使用java instrumentation和asm框架进行类转换。
我的目标是跟踪创建的每个对象,这意味着我需要定期检查它们的大小。我可以检查是否使用asm创建了新对象。我需要的是检查从堆空间创建的对象的大小。
这方面有什么指示?
于2013年12月28日编辑
好的,我能够从ASM做一些事情虽然它可能不是最好的解决方案(我完全同意的最佳方式是JVMTI
。)
我必须覆盖visitVarInsn
(对于局部变量),visitFieldInsn
(例如和类变量)和visitTypeInsn
(对于NEW
和NEWARRAY
对象得到创造)
每次创建一个新对象时,我都会记录该对象(是的,这不是我知道的好方法,这可能会导致资源泄漏。如果你有更好的解决方案,请告诉我。我需要它太糟糕了 [:(]) 我会定期检查对象大小。
你能为我提供更好的选择吗? (正如史蒂芬正确地指出的那样,这个对象记录肯定不会起作用,但我对JVMTI
[[((])感到不舒服。另外,原谅我的无知,我找不到合适的{{1方法。
MemoryMXBean有MXBean
,但我无法通过此方法跟踪单个对象的大小。也许我应该写自己的getHeapMemoryUsage()
。
答案 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);