java内存泄露学习笔记

来源:互联网 发布:阿里云服务器cpu100 编辑:程序博客网 时间:2024/05/02 08:17
 

在学C的时候,就听老师讲过内存泄露,那时候理解了,后来学java,听说有GC,内存泄露问题就解决了。再后来,找实习工作的时候,面试的一个问题是

java里面有内存泄露吗?如果有,怎样才能尽可能减少出现内存泄露的情况?

当时我答案是:  java里面有内存泄露;显式将无用对象引用置空null

 

那时候有点菜,不是很理解,答案基本都是背的。现在学习了一段时间jvm ,有了更深的理解现在,我们来解决那2个问题。

 

 

首先,java里面有内存泄露吗?

那么,我们先弄清楚第一个问题,什么是内存泄露?

官方定义:当以前分配的一片内存不再需要使用无法访问时,但是却并没有释放它,那么对于该进程来说,会因此导致总可用内存的减少,这时就出现了内存泄漏

在C里面:在内存中,分配了一块空间,用来放某个对象,这个对象必须有东西指向它,指针就是这个作用。可是,指针是比较随意的,你想让它指哪就指哪,当你把指针指向其他地方时,它原本指向的那个对象就永远也访问不到了,真悲哀,既然访问不到,又占着内存,真是占着茅坑不拉屎,由于c里面没有GC,所以就照成了内存泄露。这是无法访问的这种情况出现的内存泄露。

在java里面,好像java是不会有无法访问这种情况的内存泄露的(严格来说,还是会有,后面会讲到),因为在java中,有GC存在,只要出现了那种情况,我们的GC就开始出动了。可是,可是,大家想想,GC有那么牛B吗?每次都能找到那些不被引用的对象?万事没有绝对嘛,例如,拙劣的引用计数算法,会出现这种情况,具体实例请查看《深入理解java虚拟》P45面。根搜索算法(追踪算法)就不会出现这种情况啦。因此,java里面会不会有这种情况,取决于GC寻找无用对象的算法是否牛X。

另外一种内存泄露,就是不再需要使用。这个情况就比较麻烦了,在c和java中,都很麻烦。这个要靠程序员自己来判断和解决。我引用网上一段出现这种情况的代码:

在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个Vector中,如果我们仅仅释放引用本身,那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null

 

 

Vector v=new Vector(10);  
for (int i=1;i<100; i++)  
{  
Object o=new Object();  
v.add(o);  
o=null;  
}   //此时,所有的Object对象都没有被释放,因为变量v引用这些对象。

 

 

好了,解决了第一个问题,我们看看第二个问题,java中,怎样才能尽可能减少出现内存泄露的情况?

我们根据内存泄露的定义来寻找答案,只要不满足内存泄露的条件即可。

1、条件1:对象不可达,产生的泄露。 

          解决办法是选择一个好的GC算法,让它尽可能的能够帮我们在堆栈寻找到这样的无用对象。

2、条件2:对象无用,但是可达

        A、可达,那么我们就让它不可达嘛,如果一个对象你确定它无用,显式的把引用置为空,要考虑周全啊,因为一个对象可能有多个引用它。

        B、一个对象容易无用,那么你就把它的作用域尽量的减小,当它离开自己的作用域时,jvm会自动把它置为空。尽量不要把只用到一次的变量设成静态变量,或者全局变量,因为他们是放在方法区的(传说中的永久区),垃圾基本很少回收那的东西。

 

 

好了,暂时想到的就这么点,如果有我还会补充的。