圖片加載<第三篇>:垃圾回收機制

(1)垃圾回收機制的意義

java 語言中一個顯著的特點就是引入了java回收機制,是c++程序員最頭疼的內存管理的問題迎刃而解,它使得java程序員在編寫程序的時候不在考慮內存管理。由於有個垃圾回收機制,java中的額對象不在有“作用域”的概念,只有對象的引用纔有“作用域”。垃圾回收可以有效的防止內存泄露,有效的使用空閒的內存;

說到這,不得不提起內存泄漏(memory leak)和內存溢出(out of memory)

(2)內存泄漏內存溢出

內存泄漏: 是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄漏似乎不會有大的影響,但內存泄漏堆積後的後果就是內存溢出。

內存溢出: 指程序申請內存時,沒有足夠的內存供申請者使用,或者說,給了你一塊存儲int類型數據的存儲空間,但是你卻存儲long類型的數據,那麼結果就是內存不夠用,此時就會報錯OOM,即所謂的內存溢出。

內存泄露量大到一定程度會導致內存溢出。但是內存溢出不一定是內存泄露引起的。

(3)內存泄漏的分類(按發生方式來分類)

常發性內存泄漏: 發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。
偶發性內存泄漏: 發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測內存泄漏至關重要。
一次性內存泄漏: 發生內存泄漏的代碼只會被執行一次,或者由於算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。比如,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內存泄漏只會發生一次。
隱式內存泄漏: 程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。嚴格的說這裏並沒有發生內存泄漏,因爲最終程序釋放了所有申請的內存。但是對於一個服務器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。所以,我們稱這類內存泄漏爲隱式內存泄漏

(4)內存溢出原因
  1. 內存中加載的數據量過於龐大,如一次從數據庫取出過多數據;
  2. 集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;
  3. 代碼中存在死循環或循環產生過多重複的對象實體;
  4. 使用的第三方軟件中的BUG;
  5. 啓動參數內存值設定的過小;
(5)GC

Android觸發垃圾回收機制的時機是無法確定的,但是可以執行

            System.gc();

主動觸發垃圾回收機制。

(6)Android代碼中的堆和棧

瞭解垃圾回收機制,必須瞭解堆和棧的關係,上面是我用畫圖工具畫的簡單圖。

首先我畫了兩個矩形區域,一個代表棧空間(負責存儲對象的引用),一個代表堆空間(負責存儲對象的實例),c是一個引用,存入棧空間,new Object()是對象,存入堆空間,兩者存在引用關係,用一根直線來表示。

重點知識: 因爲存在引用關係,所以垃圾回收機制是無法回收這個對象的。

當執行以下代碼時,引用將會斷掉

c = null;

這時,下次垃圾回收機制觸發時,Object的實例會被回收。

由於引用存入棧空間佔用空間很小,對象存入堆中佔用空間很大,所以將堆中無引用的對象回收是垃圾回收機制的主要工作。

那麼,是否只要執行了c = null;,垃圾回收機制就一定會將對象回收呢?

答案是不一定。我再畫一個簡單圖來說明:

這是一個 簡單的樹形結構,GC Roots是垃圾回收機制樹形結構的根節點,當對象存在引用時,我們就在GC Roots和對象之間畫一條直線,如果設置爲null

a = null;

GC Roots和a的連線就會斷開,如圖:

這種情況下,當垃圾回收機制觸發時,由於a對象和b對象也存在引用關係,所以對象a不會被回收,這樣就造成了內存泄漏。

(7)原理

本來想畫個圖來說一下垃圾回收機制的原理的,後來發現圖畫的並不咋滴,然後我查找了很多很多有關垃圾回收機制的文章,最後終於找到一篇和我腦海中的圖差不多的,Java 技術之垃圾回收機制,這篇文章寫得非常不錯,只能用牛逼來形容,我也認真讀完了,大家看一下這篇文章的這張圖

頂端有一個節點是GC Roots,這是垃圾回收機制樹形結構的根節點,其中object 1、object 2、object 3、object 4和GC Roots存在直接或者間接的引用,object 5、object 6、object 7和GC Roots不存在引用,那麼可以總結爲:

  • object 1、object 2、object 3、object 4與根節點仍然存在引用;
  • object 5、object 6、object 7與根節點不存在引用,所以可以被GC回收。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章