2011-11-11 71 views
5

我已使用Profiler監視我的Java應用程序以瞭解內存泄漏。而我得到了它採取的內存是如何增加FinalizerThread在GC中收集對象的優先級

java.lang.ref.Finalizer 

近80%的類然後我谷歌它上面的類,發現大文章 http://www.fasterj.com/articles/finalizer1.shtml

現在可以在任何一個建議我我如何增加FinalizerThread的優先收集這些對象的GC。

還有一件事我現在面臨這個問題在Linux內核版本的Linux 2.6.9-5.ELsmp(I386)的Linux 2.6.18-194.17.4.el5(I386),但它的正常工作(沒有OOM錯誤) Linux 2.6.18-128.el5PAE(i386)。

這是因爲Linux內核的問題嗎? 是否有任何JVM變量來提高FinalizerThread的優先級?

Thanx提前。

+1

好問題,我認爲你一般需要最小化終結器的使用。 –

+0

也許在PAE模式下,你只是有更多的內存可用(非PAE限於4GB) - 檢查'免費'。我不認爲內核版本在這裏玩。 –

+0

感謝丹,正如彼得建議下面,我現在檢查文件系統。 – user1041580

回答

2

要回答這個問題,字面上你可以做到這一點。但是,如下所述,它可能是毫無意義的,尤其是線程已經具有高優先級。

for(Thread t: Thread.getAllStackTraces().keySet()) 
    if (t.getName().equals("Finalizer")) { 
     System.out.println(t); 
     t.setPriority(Thread.MAX_PRIORITY); 
     System.out.println(t); 
    } 

打印

Thread[Finalizer,8,system] 
Thread[Finalizer,10,system] 

除非您使用的所有核心100%,或接近它,優先級並不重要,因爲即使是最低的優先級將獲得儘可能多的CPU如其所願。

注意:在Linux上,它將忽略引發的優先級,除非您是root用戶。

相反,你應該減少終結者正在做的工作。理想情況下,它不應該有任何事情要做。終結者高負荷的一個原因是創造應該關閉但是被丟棄的資源。 (而不是終結器來關閉資源)

簡而言之,您應該嘗試確定哪些資源正在定稿,並確保在調用finalize()時不需要執行任何操作,理想情況下不要使用這個方法完全可以。

資源在較早版本的Linux內核上花費較長時間才能關閉。我會檢查硬件是否相同,因爲這可能意味着清理資源需要更長的時間。 (但真正的解決辦法是確保它不需要做到這一點)

+0

是java可以做出區別。因爲前兩個Linux(其中OOM問題出現),我使用64位的Java和一個工作正常,我使用32位? – user1041580

+0

Java版本,無論您使用的是64位還是32位,您使用的CPU,內存,磁盤,網絡帶寬和工作負載等硬件。它是否做了不同的工作,關閉資源的繁忙程度如何如果他們連接到數據庫或服務都在這種情況下有所作爲。內核版本可能會有所作爲,但我會先檢查第一個列表。 –

+0

如果您有較舊版本的Java,則64位版本可以使用比32位版本更多的內存。如果你有最新版本,差異要小得多(因爲它使用'-XX:+ UseCompressedOops')。真正的修復是修復代碼,而不是修補JVM。 –

2

終結者線程應該很少做很多工作。資源應該已經被釋放。確保你的代碼以標準方式處理資源。

的Java SE 7:

try (final Resource resource = acquire()) { 
    use(resource); 
} 

前的Java SE 7:

final Resource resource = acquire(); 
try { 
    use(resource); 
} finally { 
    resource.release(); 
} 
0

正如湯姆Hawtin指出的那樣,你可以通過創建一個finalize()方法調用Thread.currentThread()得到FinalizerThread的保持和然後將其存儲在靜態中。你也可以改變它的優先級。

但是有一個很好的機會,它不會有任何好處。可能只有一個終結器線程。而問題可能是,要麼:

  • 線程跟不上,因爲有隻是太多的工作要做,或
  • 線程被東西堵住你正在做的終結方法。

(而且,我期望的終結線程已經被標記爲高優先級。)

但無論哪種方式,我認爲,更好的辦法是擺脫finalize()方法。我敢打賭,他們正在做的事情是不必要的或狡猾的。特別是,使用終結器從丟棄的對象中回收資源是解決該特定問題的一種很差的方法。 (請參閱湯姆霍金的回答。)

+0

獲取終結器線程對象?簡單。用靜態方法將'Thread.currentThread()'儲存起來的終結器創建一個對象。 –