JAVA工程項目為何經常發生內存洩漏的問題?

編程語言 Java 工程師 程序員 techviewer 2017-06-04

網上經常有java黨和c++黨關於內存管理的爭論,java黨常常以內存管理簡單作為java語言的巨大優勢。工程師只用關心objects本身而將內存管理交給Java Garbage Collector來進行allocate和free是java一直鼓吹的編程方法論。

而真正使用java進行大規模的工程開發的朋友應該能理解,所謂的內存管理其實也只能做到很小的一部分。而內存洩漏總是會發生在任何一個部分,任何一個時候,造成許多的生產環境災難。

什麼是內存洩漏?

簡單的說就是一個object將不再被使用了,但是它所申請的內存空間卻不能被GC回收(原因是依舊被某一部分引用了)。簡單的用圖片來表示的話就是如下圖:

JAVA工程項目為何經常發生內存洩漏的問題?

GC要做的就是找到紅色區域進行回收,而那些referenced的對象則不會被回收。兩者交接處則是一些永遠不會再被使用,卻依舊被引用的對象,這些就是內存洩漏的地方。

那這些對象是如何產生的呢?讓我們再來看看一個例子。

JAVA工程項目為何經常發生內存洩漏的問題?

每個對象都有不同的生存週期。在上圖中對象A的生存週期是(t4-t1),對象B則是(t3-t2)。A在使用中引用了B。B在t3之後就不再被使用,而A在t3-t4階段依舊引用著B。

在這樣的情況下,GC就是沒法對B進行垃圾回收的。那如果A引用了很多對象,且生存週期很長,那麼這些對象則統統都無法進行垃圾回收了。如果此時B也引用了不少對象,那麼就形成了一條無法回收的引用鏈,內存洩漏會不斷吞噬寶貴的內存空間,直至系統崩潰。

如何防止內存洩漏?

  1. 注意static的Hashmap, ArrayList,它們的生命週期和整個程序是一樣長的,比如很多年輕的android開發為了圖方便用很多static的object來跨activity調用,你應該好好查一下自己app的內存使用量

  2. 注意事件監聽和callback,這些監聽的Listenner和callback一旦註冊了,一定要自己顯式的unregister掉

  3. 如果一個類有自己的內存空間,程序員一定要自己把那些不用的object設置成null告訴gc來回收

相關推薦

推薦中...