您的位置:首页 > Web前端

Effective java2——内存泄露

2014-09-12 14:41 267 查看
JVM提供了垃圾回收器,java程序员再也不用像C/C++程序员一样整体为对象的清理工作而焦头烂额,但是并非说java中不存在内存泄露的情况,下面展示一个典型的内存泄露的例子。

使用数组作为底层数据结构实现一个Stack栈数据结构的容器,代码如下:

public class Stack{

private Object[] elements;

private int size = 0;

private static final int DEFAULT_SIZE = 15;

public Stack(){

elements = new Object[DEFAULT_SIZE];

}

public void push(Object o){

ensureCapatity();

elements[size++]=0;

}

public Object pop(){

if(size == 0){

throw new EmptyStackException();

}

return elements[--size];

}

//如果栈已满,则将容量扩大一倍

public ensureCapatity(){

if(elements.length == size){

elements = Arrays.copyOf(elements,2*size + 1);

}

}

}

咋一看可能看不出什么问题,相信很多人也写过这样的代码,如果使用大量数据测试就会发现内存持续上升,如果把测试数据增大一倍,发现内存也跟着增长一倍,这就产生了典型的内存泄露情况。仔细研究出栈pop()操作,你会发现,栈中存在大量的无法被引用的对象,因为出栈之后并没有将元素标记为不再使用,这些在size之后的元素就成了无法被访问的无效引用对象,但是由于stack栈对象本身还是有效引用,因此这些无效的引用无法被垃圾回收器回收,造成内存泄露。

解决上述例子内存泄露的方法也很简单,重新pop()方法如下:

public Object pop(){

if(size==0){

throw new EmptyStackException();

}

Object result = elements[--size];

elements[size] == null;//将已经出栈的元素置为null,垃圾回收器就会清理这些对象

return result;

}

java中经常引起内存泄露的情况及解决方法:

(1)长生命周期的集合容器对象中存在大量无效引用的短生命元素对象:将容器中不再使用的对象标记为null,以防止产生无法访问的无效引用。

(2)通知的资源访问,如namingservice,cache等等:定时清理;使用WeakRefrence弱引用;使用WeakHashMap容器等。

(3)监听器和callback回调函数。使用WeakReference弱引用;使用WeakHashMap容器等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: