如何防止java中的内存泄漏

来源:互联网 发布:sql 统计最大值最小值 编辑:程序博客网 时间:2024/05/18 13:07

前些天紧急出版本,发现一个内存泄漏问题,程序每次注销都会有大量的对象没有释放,在
注销登陆成功后,又会重新生成一个相同的对象。这样,在做界面自动化测试的过程中,系统
频繁注销,登陆,再注销。这样如此反复多次,会必然导致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);
  }
 }

一点积累,如有错误之处,还请各位大侠指导。欢迎邮件交流:abin2012@21cn.com.

原创粉丝点击