都说java有垃圾自动回收机制,但是在开发过程中仍然有可能导致内存泄漏问题。下面有几种造成内存泄漏的来源。
一、过期引用
看下面的代码,这个简单的栈就存在“过期引用”的问题。当栈进行增长再收缩时,栈里面弹出的对象不会被当做垃圾回收,它内部仍然维护着这些过期对象的引用。GC会认为这些对象是仍然被使用的,随着程序运行时间的增长,过期对象的引用所占的内存越来越大,导致程序性能下降。
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
解决方法是:当这些引用过期的时候,手动清空这些引用。
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object obj = elements[--size];
// 清空引用
elements[size] = null;
return obj;
}
什么时候应该去手动清空引用?
一般来说,自己管理内存的时候,就应该注意内存泄漏问题。当自己开辟了一块空间的时候就有责任对这块空间进行管理,因为GC知道这块内存是已经被使用了,除非告诉它(手动清空引用),它才会自动回收。
二、缓存
内存泄漏的另一个常见来源是缓存。一旦把对象放在缓存里,它会有很长一段时间存留在缓存中。
未完待续