2015-11-04 49 views
2

有沒有辦法查看哪些實例正在垃圾收集?清單實例正在垃圾收集

我試過-XX:+PrintGC-XX:+PrintGCDetails,但只顯示釋放的內存量。

編輯:在這種特殊情況下,問題是,我的java程序規模在不斷擴大,而且我使用了大量的線程,並且據我所知,用於所有線程內存不在堆大小上,但在線程堆棧中,我不知道如何檢查它的狀態。

+2

哪些*類*或哪些*實例*? – TheLostMind

+0

已將其更正爲實例。 –

+0

你想要的是一個內存分析器。 – the8472

回答

2

不,您不會通過日誌記錄從JVM中獲取實例級別的信息(類不是GC-d)信息,因此沒有這種設置。

唯一不錯的選擇是深入瞭解GC如何針對特定類別的實例執行操作,並將其與memory dumps進行比較。通過這種方式,您可以從保留的特定類中發現大量實例。 (例如,你不小心保持引用一組流對象)

UPDATE:

既然你提到你有多個線程,對更多的信息。線程堆棧只包含本地基元,而不包含對象引用。所以很可能你在堆轉儲中找到你的溢出對象。如果您確信您的問題是由您的線程數量所致,則需要使用-Xss選項開始配置允許的堆棧大小。由於該內存即使未被線程使用也會被保留,因此您可能會因爲產生太多線程而耗盡內存。

+0

問題是我的java進程大小正在增加,並且我使用了很多**線程,而據我所知,用於所有線程的內存不在堆大小上,而是在線程堆棧,我不知道如何檢查它的狀態。 –

+0

@balizeiro顯而易見的解決方案是:不要使用很多線程。它們只會減慢應用程序的速度。 – biziclop

1

如果你想監控具體類的實例,你可以讓他們重寫finalize()方法,它是實例被垃圾回收時稱爲:

@Override 
protected void finalize() throws Throwable { 
    super.finalize(); 
    // log whatever here 
} 

下面是一些測試代碼示出它在行動:

public class MyClass { 

    public static void main(String[] args) throws Exception { 
     new MyClass(); 
     System.gc(); 
     Thread.sleep(1000); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     super.finalize(); 
     System.out.println("Goodbye, cruel world!"); 
    } 
} 

輸出:

Goodbye, cruel world! 
+1

'finalize'不保證對象是或將要被垃圾收集,而應該使用幻影引用 - 閱讀[本文獲取更多信息](https://dzone.com/articles/finalization-and-phantom )。但是請注意,當幻像引用也被垃圾收集或者包含引用的引用隊列被清除時,目標對象將僅被垃圾收集 –

+0

@RomanVottner沒有人建議'finalize'保證任何東西。但是,如果對象正在被GC調用,'finalize'保證被調用。 – Bohemian

0

和我個人理解,用於所有線程內存不上堆大小,但在線程堆棧,我不知道怎麼檢查它的狀態。

線程堆棧通常不是很大。但是一個線程可能會佔據堆上的對象。這意味着堆棧中的變量是GC根。

Yourkit profiler有GC root view。其他分析器至少應該顯示GC根目錄下任何活動對象的最短路徑。

或者,您可以簡單地附加一個調試器,暫停整個虛擬機,並使用調試器堆棧和堆行走功能來檢查當前由局部變量持有的內容。

+0

「線程棧通常不是很大。」這也是我的難處。但是現在發生的事情是這樣的:Heapsize:2Gb,Permgen:400Mb,taskmanager中的大小:8.5Gb。這就是爲什麼我認爲其他6GB必須在所有線程的堆棧 –

+1

「任務管理器中的大小」似乎是你原來的問題,然後,看起來像你正在遭受[XY問題](http:// xyproblem.info/),因爲你只是*假設*這是線程。你可能應該看看更一般的SO問題,如何找出真正消耗記憶的東西,或者如果找不到任何東西,可以提出一個新問題。 – the8472

+0

我沒有假設一個XY問題,因爲我已經對我的應用程序進行了描述,並且在GC運行後沒有發現任何東西保存在堆中。這就是爲什麼我試圖找到一種方法來查看線程發生了什麼,因爲它們保留在JVM的不同部分。 –