内存泄露
内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
Java中的内存泄露
Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露。对象都是有生命周期的,有的长,有的短,如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露。
例子:
1 public class Simple {
2 Object object;
3 public void method1(){
4 object = new Object();
5 //...其他代码
6 }
7 }
这里的object实例,其实我们期望它只作用于method1()方法中,且其他地方不会再用到它,但是,当method1()方法执行完成后,object对象所分配的内存不会马上被认为是可以被释放的对象,只有在Simple类创建的对象被释放后才会被释放,严格的说,这就是一种内存泄露。解决方法就是将object作为method1()方法中的局部变量,或者,在method其他代码之后执行object = null。
预防内存泄露
预防内存泄露的原则就是尽量减小对象的作用域,建议是将类的成员变量改写为方法内的局部变量)以及手动设置null值。
Java之LinkedList源码(JDK 1.8)
1 //删除指定节点并返回被删除的元素值
2 E unlink(Node<E> x) {
3 //获取当前值和前后节点
4 final E element = x.item;
5 final Node<E> next = x.next;
6 final Node<E> prev = x.prev;
7 if (prev == null) {
8 first = next; //如果前一个节点为空(如当前节点为首节点),后一个节点成为新的首节点
9 } else {
10 prev.next = next;//如果前一个节点不为空,那么他先后指向当前的下一个节点
11 x.prev = null;
12 }
13 if (next == null) {
14 last = prev; //如果后一个节点为空(如当前节点为尾节点),当前节点前一个成为新的尾节点
15 } else {
16 next.prev = prev;//如果后一个节点不为空,后一个节点向前指向当前的前一个节点
17 x.next = null;
18 }
19 x.item = null;
20 size--;
21 modCount++;
22 return element;
23 }
这段代码就非常好的将无用变量至null,使得空间得以迅速回收。
Java之ArrayList源码(JDK 1.8)
1 public E pop(){
2 if(size == 0)
3 return null;
4 else
5 return (E) elementData[--size];
6 }
写法很简洁,但这里却会造成内存溢出:elementData[size-1]依然持有E类型对象的引用,并且暂时不能被GC回收。我们可以如下修改:
1 public E pop(){
2 if(size == 0)
3 return null;
4 else{
5 E e = (E) elementData[--size];
6 elementData[size] = null;
7 return e;
8 }
9 }