所謂內存泄露就是指一個不再被程序使用的對象或變量一直被占據在內存中。Java中有垃圾回收機制,它可以保證一對象不再被引用的時候,即對象編程了孤兒的時候,對象將自動被垃圾回收器從內存中清除掉。由於Java 使用有向圖的方式進行垃圾回收管理,可以消除引用循環的問題,例如有兩個對象,相互引用,只要它們和根進程不可達的,那么GC也是可以回收它們的。
package com.huawei.interview;
import java.io.IOException;
public class GarbageTest {
/** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub try { gcTest(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("has exited gcTest!"); System.in.read(); System.in.read(); System.out.println("out begin gc!"); for(int i=0;i<100;i++) { System.gc(); System.in.read(); System.in.read(); } } private static void gcTest() throws IOException { System.in.read(); System.in.read(); Person p1 = new Person(); System.in.read(); System.in.read(); Person p2 = new Person(); p1.setMate(p2); p2.setMate(p1); System.out.println("before exit gctest!"); System.in.read(); System.in.read(); System.gc(); System.out.println("exit gctest!"); } private static class Person { byte[] data = new byte[20000000]; Person mate = null; public void setMate(Person other) { mate = other; } } }
java中的內存泄露的情況:長生命周期的對象持有短生命周期對象的引用就很可能發生內存泄露,盡管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內存泄露的發生場景,通俗地說,就是程序員可能創建了一個對象,以后一直不再使用這個對象,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的,這就是java中可能出現內存泄露的情況,例如,緩存系統,我們加載了一個對象放在緩存中(例如放在一個全局map對象中),然后一直不再使用它,這個對象一直被緩存引用,但卻不再被使用。
檢查java中的內存泄露,一定要讓程序將各種分支情況都完整執行到程序結束,然后看某個對象是否被使用過,如果沒有,則才能判定這個對象屬於內存泄露。
如果一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由於內部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄露。
public class Stack {
private Object[] elements=new Object[10];
private int size = 0;
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);
}
}
}
內存泄露的另外一種情況:當一個對象被存儲進HashSet集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改后的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作為的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄露