不使用本机代码跟踪java堆
有一段时间我一直在摆弄Java堆。使用不使用本机代码跟踪java堆,java,assembly,bytecode,Java,Assembly,Bytecode,有一段时间我一直在摆弄Java堆。使用JVMTI,我们可以跟踪java堆 但是,有没有办法用纯java实现同样的功能呢 我在运行时使用java插装和asm框架进行类转换 我的目标是跟踪创建的每个对象,这意味着我需要定期检查它们的大小。我可以检查是否使用asm创建了新对象。我需要检查从堆空间创建的对象的大小 在这方面有什么建议吗 于2013年12月28日编辑 好的,我可以从ASM中做一些事情,尽管这可能不是最好的解决方案(最好的方法是JVMTI,我完全同意) 我必须重写visitVarInsn(对
JVMTI
,我们可以跟踪java堆
但是,有没有办法用纯java实现同样的功能呢
我在运行时使用java插装和asm框架进行类转换
我的目标是跟踪创建的每个对象,这意味着我需要定期检查它们的大小。我可以检查是否使用asm创建了新对象。我需要检查从堆空间创建的对象的大小
在这方面有什么建议吗
于2013年12月28日编辑
好的,我可以从ASM中做一些事情,尽管这可能不是最好的解决方案(最好的方法是JVMTI
,我完全同意)
我必须重写visitVarInsn
(对于局部变量)、visitFieldInsn
(例如和类变量)和visitTypeInsn
(对于创建的NEW
和NEWARRAY
对象)
每次创建新对象时,我都会记录该对象(是的,我知道这不是一个好方法,这可能会导致资源泄漏。如果您有更好的解决方案,请告诉我。我非常需要它[:(]))
我会定期检查物体的大小
你能给我提供更好的选择吗?(正如Stephen正确地指出的那样,这个对象录制肯定不起作用,但我对JVMTI
也不满意[:(])。另外,请原谅我的无知,我找不到合适的MXBean
方法
具有
getHeapMemoryUsage()
,但我无法通过此方法跟踪单个对象的大小。可能是我应该编写自己的MBean
使用运行时
类
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);
我想你理论上可以这么做。对象的(浅)大小很容易从对象字段的数量和类型计算出来,你可以使用ASM工具向每个构造函数插入代码,以便在每次构造对象时记录大小(某处) 处理数组会很棘手。数组分配不需要构造函数,因此您需要在创建数组的所有位置插入指令。由于其中一些位置可能在本机代码中,因此很难看到如何执行此操作 另一个棘手的情况是处理在不调用构造函数的情况下创建对象的事情;例如对象序列化和本机克隆 总而言之,这可能不是一个实际的方法
另一点是,任何使用ASM和类似东西的东西都可以说不是“纯Java”…除非使用实际上是JVM本身的一部分。因为您使用的是检测,所以您已经可以访问告诉您对象大小的API。您用来修改类的字节码的类提供了该方法 您提到的有关对象跟踪的资源泄漏问题可以很容易地解决。只需将对象放入s。然后您就可以使用a来了解对象何时被垃圾收集,这是您想要跟踪堆使用情况的一个重要功能 但我不太确定你到底想要实现什么
顺便说一句,据我所知,JVM不使用JVMTI。但JVMTI也不跟踪每个对象。完整堆分析需要堆转储。这可以通过发送方法调用来完成。你看过了吗?@ElliottFrisch:是的,但我相信它使用JVMTI。嗨@Ankit,这将给出基于JVM大小。但我需要堆中的每个对象大小。不仅如此,我还想检查堆中的对象数量,我正在使用
visitTypeInsn
跟踪对象实例化。但是,创建对象后,我如何处理它?我需要将对象列表存储在某个集合对象中,对吗?你应该在你的统计数据中记录对象的大小。如果你开始记录对象本身,你很可能会造成大规模的存储泄漏。但正如我所说,我认为这种方法不实用。使用JVMTI,你会得到更准确的结果,问题更少。(使用它有什么问题??)还应该指出的是,JVM中的这种内存使用计算只是为了娱乐——我的意思是估计——目的。如果您想查看有用的内存使用统计数据,请使用JMX。当您加入诸如压缩OOP和转义分析之类的内容时,您真的无法可靠地确定对象将占用多少堆p、 @CharlesForsythe:事实上,我的一个关键要求是向后兼容JDK1.5。我已经检查了各种MXBean
sMemoryMXBean
,MemoryPoolMXBean
,MemoryManagerMXBean
提供了关于堆的有用信息,但我无法从中跟踪任何特定的对象大小。可以吗是不是我在使用JMX时遗漏了一些东西。我说得对吗?@StephenC:是的,我完全同意你的看法。使用JVMTI
会让我在几次打嗝后就有了完整的画面。但是,老实说,我对JVMTI
感到不舒服。如果在java透视图中什么都做不了,那么我就别无选择,只能转到JVMTI.是的,我正在使用getObjectSize(Object)
方法,然后我正在使用反射遍历对象以获得其实际大小。ok..我将尝试ReferenceQueue
方法并相应地更新您。我只想跟踪对象大小,就是这样。:-)是的,我可以使用获取堆转储来实现这一点,但我猜获取的数量太多(而且频繁)堆转储对于应用程序来说可能很昂贵。如果我错了,请纠正我。如果我将对象放在WeakHashMap
中,并将它们作为键,那么jvm本身将检查弱引用,并在对象被垃圾收集时从映射中删除条目