2016-11-14 42 views
1

我想知道是否有任何輕量級的方法來(粗略地)測量一個給定的Java類正在使用多少內存。讓我們考慮以下接口:監視Java對象在特定方法中的分配/釋放

interface MyAction <T, R> { 
    R execute(T item); 
} 

我想知道有多少內存作爲實例字段中的所有對象或作爲overrided執行方法變量使用。當然,它也應該考慮調用其他方法時創建的每個對象。 至於我能理解(閱讀本reply)最好的辦法是:

  • 補丁JVM字節碼通過ASM框架和地方鉤之前的任何下列指令:新,newarray,anewarray,multianewarray。

  • 通過更改JNI函數表來攔截所有的JNI調用(如果有的話)。

  • 攔截所有VMObjectAlloc事件。

這3個步驟將涵蓋每一個可能的分配,但我無法弄清楚是否有任何好的方法來跟蹤對象的重新分配。

我會修補finalize方法字節碼,以便獲得有關對象gc釋放和攔截所有ObjectFree事件(僅用於標記對象)的通知。我確信這不會涵蓋所有的釋放事件,因此我想知道是否有一些已知的技術(我無法找到)可以幫助我解決這個問題。

預先感謝您。

+1

只是想知道:爲什麼你想知道這一切? – GhostCat

+0

如果您想進行一些手動分析,您可以創建一個堆轉儲並使用Eclipse MAT等工具對其進行分析。除此之外,解除分配應該可以通過'finalize()'來跟蹤,但是由於vm不能保證不需要的對象永遠不會被終結,我不會指望這一點。實際上,你可以將任何不能從活動線程訪問的對象作爲垃圾收集/解除分配的可用對象,但在運行時分析它可能會花費相當多的成本,而現有的堆轉儲分析器將完全適合您。 – Thomas

+0

說實話,我想在運行時知道這樣的信息,因爲我試圖優化一個已經擁有自己的內存管理系統來進行內部處理。由於代碼無法控制MyAction,所以根據實時統計進行即時調整有望導致更好的內存管理器。當然,我仍然在評估遊戲是否值得這一點。 @Thomas是的,肯定finalize()是不值得信任的。 –

回答

0

由於您對分配的內存量感興趣,而不是每個單獨分配的對象,因此可以使用更簡單的方法。

有一種方法ThreadMXBean.getThreadAllocatedBytes,它返回給定線程分配的累積內存量。在撥打execute之前和之後,您只需要記錄計數器。差異將是該方法分配的估計總內存(考慮到它不跨越多個線程)。

這裏是如何得到的com.sun.management.ThreadMXBean實例:

com.sun.management.ThreadMXBean mxBean = 
      (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); 

有作爲Java對象釋放沒有這樣的事件。完全GC之前,您無法找到對象是否可到達。即使GC不「解除分配」對象 - 它通常只是穿過活動對象,並將其他一切視爲自由空間。

如果您需要在調用方法後查找Java堆的更改方式,則可以在調用之前和之後創建堆快照。

+0

謝謝您的回覆。不幸的是,這不是我的情況,因爲我需要在執行我的方法期間監視分配情況。此外,我不能只爲該方法調用專用的線程。這個想法是根據execute()方法中的內存消耗調整系統中使用的java.nio.ByteBuffer的數量。然而,只要有可能進行每個線程堆轉儲,我認爲這是不可行的,那麼關於堆快照的想法可能會很有趣。 –