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() 真正清除键值对。