一個記憶體洩漏的例子
阿新 • • 發佈:2018-11-11
記憶體洩漏
看一個例子:
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];
}
public void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
這段程式碼存在一個記憶體洩漏問題:如果一個棧先增長,再收縮,那麼從棧中彈出的元素不會被當做垃圾回收;即使棧的程式不在引用這些物件,他們也不會被回收.
這是因為,棧內部維護著這些物件的過期引用
記憶體洩漏的來源可能:
- 自己管理記憶體的類,如Stack;
- 快取(使用weakHashMap或由後臺執行緒定時清理)
- 監聽器和其他回撥
Stack正是由於自己管理記憶體的特性使它容易遭受記憶體洩漏的影響;
修復:一旦物件引用已經過期,只需清理這些引用即可;對於上面的例子而言,一旦元素從棧中彈出,指向它的引用就過期了;pop方法修改如下:
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
element[size]=null//消除過期引用
return result ;
}
weakHashMap
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;
public class WeakHashMapTester {
static Map<String, String> wMap = new WeakHashMap<String, String>();
static Map<String, String> map = new HashMap<String, String>();
static {
String ref1 = new String("obejct1");
String ref2 = new String("obejct2");
wMap.put(ref1, "chaheObject1");
map.put(ref2, "chaheObject2");
}
public static void TestWeahHashMap() {
System.out.println("WeakHashMap GC之前");
for (Entry<String, String> str : wMap.entrySet()) {
System.out.println(str);
}
System.gc();
System.out.println("WeakHashMap GC之後");
for (Entry<String, String> str : wMap.entrySet()) {
System.out.println(str);
}
}
public static void TestHashMap() {
System.out.println("HashMap GC之前");
for (Entry<String, String> str : map.entrySet()) {
System.out.println(str);
}
System.gc();
System.out.println("HashMap GC之後");
for (Entry<String, String> str : map.entrySet()) {
System.out.println(str);
}
}
public static void main(String[] args) {
TestWeahHashMap();
System.out.println("---------");
TestHashMap();
}
}
結果:
WeakHashMap GC之前
obejct1=chaheObject1
WeakHashMap GC之後
---------
HashMap GC之前
obejct2=chaheObject2
HashMap GC之後
obejct2=chaheObject2
更多:https://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java/6471947#6471947
Effective java