每當我的JVM創建一個新對象時,我想在日誌中打印一些東西。我試圖使用Runtime.getRuntime()。freeMemory()來檢測它,但不幸的是它沒有考慮到任何短暫的對象,直到它被提升到堆(check here for more details)。如何跟蹤Java中的任何對象創建,因爲freeMemory()僅報告長壽命對象?
那麼有沒有人知道如何檢測/跟蹤每當一個對象被實例化/由我的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());
}
但它確實acco對於任何對象的創建,所以我想我可以使用這個,如果我從它減去魔術數字48。
是否使用AspectJ選項?如果是這樣,這個問題可能包含的代碼可以被修改,以便該方面觸發任何構造函數的調用:http://stackoverflow.com/questions/6402304/help-with-pointcut-aspectj – Joe23 2012-03-21 18:07:50
謝謝@ Joe23,但我我正在尋找更純粹的Java解決方案。我認爲使用JMX訪問所有內存池並添加所使用的內存可能是解決方案,所以當我增加總數時,我可以假設我在某處創建了對象(還假設GC未觸發) – chrisapotek 2012-03-21 18:10:09
我認爲您對如何理解Java堆的作品。在(慢)調試環境之外,沒有辦法做你想做的事情。 – 2012-03-21 18:20:44