【发布时间】:2012-03-21 17:58:44
【问题描述】:
每当我的 JVM 创建一个新对象时,我都想在日志中打印一些内容。我试图使用 Runtime.getRuntime().freeMemory() 检测到这一点,但不幸的是,在将其提升到堆 (check here for more details) 之前,它不会考虑任何短期对象。
那么有谁知道我的 JVM 实例化/创建对象时如何检测/跟踪?为方便起见,我们如何完成下面的代码:
随意使用 MemoryPoolMXBean 和 JMX:
public class MemoryUtils {
private static Set<String> set = new HashSet<String>();
public static void main(String[] args) {
// START
// now create a bunch of objects and save them in the set
for (int i = 0; i < 100; i++) {
set.add(new String("foo" + i));
}
// FINISH
// FIXME: Do something here to detect that a bunch of objects were created!
}
}
编辑:以下弗拉基米尔提出的尝试解决方案:
它有效,但有一个奇怪的副作用:
long t = totalThreadMemoryAllocated();
// did nothing
t = totalThreadMemoryAllocated() - t;
System.out.println(t); // ==> 48 !!!???
public static long totalThreadMemoryAllocated() {
com.sun.management.ThreadMXBean tBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
return tBean.getThreadAllocatedBytes(Thread.currentThread().getId());
}
但它确实说明了任何对象的创建,所以我想如果我从中减去幻数 48 就可以使用它。
【问题讨论】:
-
是否可以选择使用 AspectJ?如果是这样,这个问题可能包含可以修改的代码,以便在任何构造函数调用时触发方面:stackoverflow.com/questions/6402304/help-with-pointcut-aspectj
-
感谢@Joe23,但我正在寻找更纯粹的 java 解决方案。我认为使用 JMX 访问所有内存池并添加使用的内存可能是解决方案,所以当我的总增加时,我可以假设我在某处创建了对象(也假设 GC 没有触发)
-
我认为您对 Java 堆的工作原理了解不足。在(缓慢的)调试环境之外,没有办法做你想做的事。
-
@Hot Licks 没有什么是不可能的。检查弗拉基米尔的答案!
-
啊,但是知道分配了多少字节几乎没用。
标签: java optimization garbage-collection jmx