前些天緊急出版本,發現一個內存泄漏問題,程序每次註銷都會有大量的對象沒有釋放,在
註銷登陸成功後,又會重新生成一個相同的對象。這樣,在做界面自動化測試的過程中,系統
頻繁註銷,登陸,再註銷。這樣如此反覆多次,會必然導致java這個進程的內存溢出OutOfMemory。
拿到問題,用JProfile把程序跑起來,查到具體泄漏的對象,然後進行詳細的分析。
發現兩個地方存在嚴重的泄漏:
1 某對象在創建,初始化的過程會創建一個線程,這個線程專門處理和計算機串口的通訊。
代碼如下:
package example;
/**
* @author zLan1028
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class MemoeryTest
{
public static void main(String[] args)
{
MemoeryTest test = new MemoeryTest();
test.init();
test = null;
//do other something
}
public void init()
{
thread.start();
}
private Thread thread = new BasicThread ();
boolean exit = false;
class BasicThread extends Thread()
{
List lstData = new LinkedList();
public void run()
{
while(!exit)
{
synchronized(lstData)
{
if (lstData.isEmpty())
{
lstData.wait();
}
writeDataToSerialPort((String)lstData.removeFirst());
}
}
}
private void writeDataToSerialPort(String str)
{
//write data to serialPort
}
};
}
請大家看,在test對象被置位null後,是否這個對象會把垃圾回收器進行自動回收?
咋一看,應該會,這個對象已經沒有其它引用存在。其實不然,因爲這個對象中創建了一個內部類。
而在java中,內部類會自動獲得一個對外部類的對象引用,而在釋放test對象時,沒有去把它內部創建的線程對象,
所以這個線程對象在程序退出前會一直存在,所以它會一直保持對外部test對象的引用,這樣,每創建一個MemoeryTest
對象,都會存在一個線程對象泄漏,而且一個MemoeryTest對象泄漏。這樣時非常危險的。
如果只對這個對象進行初始化,而在程序註銷時沒有對創建的線程資源回收,則這個問題可以避免。
代碼如下:
在MemoeryTest 對象中增加一個 public void close()方法,在每次釋放MemoeryTest 對象時,主動調用close方法釋放資源。
public void close()
{
try {
exit = true;
thread.interrupt();
thread.join();
} catch (Exception e)
{
e.printStackTrace(System.out);
}
}
一點積累,如有錯誤之處,還請各位大俠指導。歡迎郵件交流:[email protected].