2011-12-15 160 views
1

我創建的服務將不斷運行,每天在指定的時間運行程序的主體。Java內存泄漏

本質:

while(true){ 
run(); 
Thread.sleep(day); 
} 

一段時間後,我越來越OutOfMemoryHeapExceptions。 在閱讀了這篇文章之後,我想到了它,因爲run()方法內創建的任何對象都不會被垃圾收集。

所以我做一樣的東西:

public void run(){ 
Object a = new Object(); 
a.doSomething(); 

a= null; //Wasn't here before 
} 

我的問題是,這將解決我的問題?我的印象是,一旦對象爲空,它以前引用的對象將被垃圾收集?這是一個好主意嗎?或者我應該看看做別的事情?

謝謝

+0

東西沒有人回答指出運行內存,雖然它是一個微弱的可能性:你可能已經打在VM或GC的錯誤。這不太可能,但並非不可能。 – Romain 2011-12-15 12:10:06

回答

3

添加a = null幾乎肯定不足以解決問題(因爲a即將超出範圍)。

我的建議是使用內存分析器來查明什麼是泄漏和在哪裏。我個人使用YourKit。這非常好,但花錢(你可以得到免費的評估)。

另一個最近發佈的工具是Plumbr。我還沒有嘗試它,但blurb說:

試試我們的Java代理以及時發現內存泄漏。我們會告訴您泄漏的是什麼,泄漏源自哪裏以及泄漏對象當前所在的位置 - 遠在OutOfMemoryError之前!

0

您的印象不正確。在run()方法中創建的對象將被垃圾收集,只要它們1)超出範圍,並且2)已經釋放了它們正在使用的任何本地或遠程系統資源。

你在run()方法調用中實際執行了哪些功能?你正在閱讀文件,進行數據庫調用,寫入套接字?不知道細節很難提供更好的建議。

+0

那麼,如果`a.doSomething()`添加對由`a`引用的對象的引用,在退出run()`的範圍後仍然有效,該怎麼辦? – Romain 2011-12-15 12:05:59

+0

我從文件中提取信息,然後將它們插入到數據庫中。 – Craig 2011-12-15 12:08:31

+0

@Romain - 如果這些引用不在run()的範圍之內,並且與其他實時代碼隔離,並且沒有保留任何系統資源,我會希望它們正常進行GC'd。在這種情況下,我猜是有文件或數據庫句柄保持不變。 – mcfinnigan 2011-12-15 13:01:36

0

你應該得到一個內存轉儲並使用類似 JConsole JVisualVM的工具進行分析。

run()方法的範圍留在Thread.sleep(day);之前,因此該方法內的任何變量都被銷燬。之後,a將不再存在,因此該變量引用的對象可能有資格進行垃圾回收,前提是沒有其他引用

分析內存轉儲應該允許您找到對這些對象的任何引用(如果它們仍然存在)。

它可能不是那些物體,但其他的物體會保持活力,並且會消耗記憶。這取決於你在做什麼,可能很難在這裏分析。因此,根據內存使用情況查找大型對象圖。

例如,我們遇到了經常創建的數據庫連接問題(XA恢復機制),我們認爲一旦方法範圍被遺留,它們就會被銷燬。但是,服務器將這些連接放入一個靜態列表中,並且從未清除它,因此我們最終沒有真正記憶。什麼幫助我們識別出該案件正在分析內存轉儲。 :)

0

不,您不需要將該變量設置爲空。虛擬機知道你退出了這個範圍,並且變量a不再存在,所以它會自動減少引用計數,如果沒有其他引用,你的對象可以被垃圾回收所取代。

該錯誤是在別的地方。

2

這可能確實有幫助,在某些情況下,GC算法需要一點幫助來執行,但它不能保證解決您的問題,只是延遲它們。

我的建議: 用較短的時間週期模擬相同的行爲,以便強制發生錯誤。 用分析器運行它並查看所有內存在哪裏,然後從那裏開始工作。

0

將引用設置爲null取決於您的對象是否處於長時間消耗過程中的範圍內,儘管從理論上講,它將標記引用爲null,但不能保證它何時進行垃圾回收。

你需要檢查你的對象是否在你的代碼中的某個地方被長期保存。

發現設置參數的一個很好的解釋爲null:Does setting Java objects to null do anything anymore?

爲了角球開出您的問題,您需要配置您的應用程序。

搜索等都給垃圾收集如此多的三分球,我決定只將搜索字符串在這裏:

https://stackoverflow.com/search?q=Java+Garbage+collection+and+setting+references+to+null

http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

0

局部變量應該由GC收集。所以,你不需要把obj = null;。因爲Object也存儲在Heap區域。

0

在短期內,保持應用程序穩定的實用方法是在每次執行後退出JVM。使用批量調度程序(例如,在Windows上的* nix,at上的cron)每天只執行一次應用程序。任何內存泄漏都會在J​​VM存在時被清除。但是,您可能必須小心,不要讓數據庫連接處於打開狀態等。

這會給您時間解決和修復潛在的內存泄漏問題,同時保持您的生產代碼運行並且不需要支持人員重新啓動服務器等等

我假設你不是一個執行