java是具有垃圾回收功能的语言,那么我们就不再需要去考虑内存管理的事情了呢?当然不是,当你不小心时,也会导致内存泄漏
class Stack{
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity){
this.elements = new Object[initialCapacity];
}
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){
Object[] oldElements = elements;
elements = new Object[2*elements.length + 1];
System.arraycopy(oldElements, 0, elements, 0, size);
}
}
}
当使栈先是增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不在引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用。所谓过期的引用,是指永远也不会被解除的引用。例如一些容器你也可能忘了去清理。
应该这样做:
public Object pop(){
if(size == 0){
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;
return result;
}
内存泄漏的另一个常见的来源是缓存。有时候,当我们将一个对象的引用放入了缓存,很容易遗忘它。有两种常用的方式去解决:
1.利用WeakHashMap。
2.LinkedHashMap,利用它的removeEldestEntry也可以实现对缓存的清除
关于WeakHashMap的知识,介绍:
HashMap: https://blog.csdn.net/hxpjava1/article/details/55670439
WeakHashMap: https://www.cnblogs.com/redcreen/archive/2011/02/15/1955289.html
https://blog.csdn.net/u012129558/article/details/51980883
WeakHashMap和HashMap实现基本相同,最关键是有一个 ReferenceQueue<K> queue 保存需要清除的key和 expungeStaleEntries() 真正清除键值对。