Java内存泄露问题

系统 1539 0

内存泄露

 

       所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。   java中有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉。由于Java 使用有向图的方式进行垃圾回收管理,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的,例如下面的代码可以看到这种情况的内存回收:

Java代码     收藏代码
  1. public   class  GarbageTest {  
  2.   
  3.      public   static   void  main(String[] args)  throws  IOException {  
  4.          try  {  
  5.             gcTest();  
  6.         }  catch  (IOException e) {  
  7.             e.printStackTrace();  
  8.         }  
  9.         System.out.println( "has exited gcTest!" );  
  10.         System.in.read();  
  11.         System.in.read();         
  12.         System.out.println( "out begin gc!" );          
  13.          for ( int  i= 0 ;i< 100 ;i++)  
  14.         {  
  15.             System.gc();  
  16.             System.in.read();     
  17.             System.in.read();     
  18.         }  
  19.     }  
  20.   
  21.      private   static   void  gcTest()  throws  IOException {  
  22.         System.in.read();  
  23.         System.in.read();         
  24.         Person p1 =  new  Person();  
  25.         System.in.read();  
  26.         System.in.read();         
  27.         Person p2 =  new  Person();  
  28.         p1.setMate(p2);  //p1中包含p2的引用   
  29.         p2.setMate(p1);  //p2中包含p1的引用   
  30.         System.out.println( "before exit gctest!" );  
  31.         System.in.read();  
  32.         System.in.read();         
  33.         System.gc();  
  34.         System.out.println( "exit gctest!" );  
  35.     }  
  36.   
  37.      private   static   class  Person  
  38.     {  
  39.          byte [] data =  new   byte [ 20000000 ];  
  40.         Person mate =  null ;  
  41.          public   void  setMate(Person other)  
  42.         {  
  43.             mate = other;  
  44.         }  
  45.     }  
  46. }  

       当gcTest()方法运行完毕以后,p1和p2对象都变成了垃圾,他们都不会被根对象所找到。关于根对象请参见《 JVM垃圾回收机制总结(2) :基本算法概述   》中的关于“垃圾回收从哪里开始”的讨论。

 

Java的内存泄露

 

虽然Java的垃圾回收机制较大程度的降低了内存泄露的可能性,但Java程序员仍然可能会写出发生内存泄露的代码。其原因就是一个已经不被使用的短寿命对象被一个长寿命对象(如类的静态成员对象)引用,这就使得本来要被回收的短寿命对象永远无法被回收,造成内存泄露。

 

 

内存泄露的典型情况

 

(1) 数据结构造成的短暂内存泄露问题,看下面的代码

Java代码     收藏代码
  1. public   class  Stack{  
  2.        private  Object[] element= new  Object[ 10 ];  
  3.        private   int  size= 0 ;  
  4.         
  5.        public   void  push(Object ele){  
  6.              ensureCapacity();  
  7.              element[size++]=ele;  
  8.       }  
  9.   
  10.        public  Object pop(){  
  11.               if (size== 0 throw   new  EmptyStackException();  
  12.               return  element[--size];  //短暂造成内存泄露   
  13.       }  
  14.   
  15.        private   void  ensureCapacity(){  
  16.               if (element.length==size){  
  17.                      Object[] oldElement=element;  
  18.                      element= new  Object[size* 2 + 1 ];  
  19.                      System.arraycopy(oldElement, 0 ,element, 0 ,size);  
  20.              }  
  21.       }  
  22. }  

       上面的代码每一次pop()的时候,Stack都会弹出一个元素,在没有加入新元素之前,实际上仍然有一个引用element[x]指向了这个已经弹出的对象,因此GC是不会对其进行垃圾回收的。只有push()新元素的时候使得element[x]=newObject,才会使得以前创建的对象有可能被回收。应该把上面的pop()方法改成下面的代码就安全多了:

Java代码     收藏代码
  1. public  Object pop(){  
  2.         if (element.length==size)  throws  EmptyStackException();  
  3.        Object o=element[--size];  
  4.        elements[size]= null ;   //使得GC有机会回收这个对象   
  5.         return  o;  
  6. }  

 

 

Java内存泄露问题


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论