2012-03-21 42 views
1

每當我的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。

+2

是否使用AspectJ選項?如果是這樣,這個問題可能包含的代碼可以被修改,以便該方面觸發任何構造函數的調用:http://stackoverflow.com/questions/6402304/help-with-pointcut-aspectj – Joe23 2012-03-21 18:07:50

+0

謝謝@ Joe23,但我我正在尋找更純粹的Java解決方案。我認爲使用JMX訪問所有內存池並添加所使用的內存可能是解決方案,所以當我增加總數時,我可以假設我在某處創建了對象(還假設GC未觸發) – chrisapotek 2012-03-21 18:10:09

+0

我認爲您對如何理解Java堆的作品。在(慢)調試環境之外,沒有辦法做你想做的事情。 – 2012-03-21 18:20:44

回答

3

Sun JVM(1.6.0u26及更高版本)有ThreadMXBean#getThreadAllocatedBytes方法報告線程分配的總字節數。 這將不會區分活/死的內存,但是這將允許您檢測內存分配並測量這些分配的總量。

要使用此方法,只需查找常規的ThreadMXBean,然後將其轉換爲com.sun.management.ThreadMXBean或使用反射來調用該方法。

+0

請參閱我上面的修改。即使我沒有做任何事情,它也會報告48.我嘗試了任何東西,而不是分配任何東西的Thread.currentThread。我認爲getThreadAllocatedBytes的調用本身以某種方式創建了48個字節。 – chrisapotek 2012-03-21 19:00:46

+0

據我所知,這些48個字節來自兩個long [1]數組:http://www.docjar.com/html/api/sun/management/ThreadImpl.java.html#321 – 2012-03-21 19:54:16

+0

@chrisapotek:如果我認爲它正確的,你運行32位JVM,所以每個數組消耗8(頭)+4(長度)+8(1項 - 長)+4(填充8字節對齊)= 24個字節。 如果測試在64位JVM getThreadAllocatedBytes,那魔48將改變爲類似2個陣列*(16 + 4 + 8 + 4)=「魔法64」 – 2012-03-21 20:03:11

0

我寫了一個開源的工具來跟蹤對象分配和對象生存:http://mchr3k.github.com/org.inmemprofiler/

我工具不會讓您將所有對象分配記錄到您自己的日誌中,但會假設您要主動跟蹤對象泄漏或過度對象分配等事情,從而執行自己的分析。