java內存泄露具體解釋
非常多人有疑問,java有非常好的垃圾回收機制,怎麽會有內存泄露?事實上是有的,那麽何為內存泄露?在Java中所謂內存泄露就是指在程序執行的過程中產生了一些對象,當不須要這些對象時,他們卻沒有被垃圾回收掉,並且程序執行中非常難發現這個對象。它始終占領著內存卻沒有發揮作用。
我舉這樣一個樣例,在現實開發中我們須要自己定義一個先進後出的棧集合,代碼例如以下:
這個代碼看起來和執行起來都沒問題,可是,這裏有個非常隱晦的問題,就是在pop()方法裏面。我們首先找到集合最後一個元素的下標。然後依照下標從集合中取出,可是這個對象真的從集合中移走了嗎?答案不是的,也就是說你取出來的對象看似從棧中取出來了。可是它卻還存在於集合中占領著內存。並且你非常難發現它,這就產生了內存泄露,正確的pop()方法應該是package cn.lmj.demo2; import java.util.ArrayList; import java.util.List; public class MyStack { private List list = new ArrayList(); private int len = 0; public void put(T obj) { list.add(obj); len++; } public T pop() { int index = --len; return list.get(index); } }
public T pop()
{
int index = --len;
return list.remove(index); //取出的同一時候刪除集合中的元素
}
在java中,還有這樣一個場景也會出現內存泄露問題,並且也是非常隱晦的,我們在用Map存一對鍵值型的數據時。我們假設存進去了,那麽就不要改動Map的key值參與計算的hashCode方法和equals方法,例如以下代碼就有內存泄露問題:
總結:package cn.lmj.demo2; import java.util.HashMap; import java.util.Map; public class Demo03 { public static void main(String[] args) { Map map = new HashMap(); Person p1 = new Person("aaa"); Person p2 = new Person("bbb"); Person p3 = new Person("ccc"); map.put(p1,"1"); map.put(p2,"2"); map.put(p3,"3"); System.out.println(map.containsKey(new Person("aaa")));//true p1.setName("eee"); //改變參與計算的hashCode和equals值 System.out.println(map.containsKey(new Person("aaa")));//false } } class Person { private String name; public Person(String name) { super(); this.name = name; } public Person() { super(); } //利用name屬性生成hashCode和equals方法 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ?
0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在java中是有內存泄露的情況。那麽我們在開發中怎樣避免內存泄露?除了上面兩種情況的以外:
1、最主要的建議是盡早釋放無用對象的引用。如:
…..
A a = new A()。
//應用a對象
a = null。 //當使用對象a之後主動將其設置為空
…
註:假設a 是方法的返回值,不要做這種處理。否則你從該方法中得到的返回值永遠為空,並且這種錯誤不易被發現、排除
2、盡量少用finalize函數。它會加大GC的工作量。
3、假設須要使用經經常使用到的圖片。能夠使用soft應用類型。
它盡可能把圖片保存在內存中
4、註意集合數據類型,包含數組、樹、圖、鏈表等數據結構,這些數據結構對GC來說。回收更為復雜。
5、盡量避免在類的默認構造器中創建、初始化大量的對象,防止在調用其自類的構造器時造成不必要的內存資源浪費
6、盡量避免強制系統做垃圾內存的回收。增長系統做垃圾回收的終於時間
7、盡量避免顯式申請數組空間
8、盡量做遠程方法調用類應用開發時使用瞬間值變量。除非遠程調用端須要獲取該瞬間值變量的值。
9、盡量在合適的場景下使用對象池技術以提高系統性能。
java內存泄露具體解釋