Android gc與內存泄漏,溢出的理解

GC介紹

在java中垃圾回收是自動釋放的,不像c/c++需要手動釋放,手動釋放可能處理不當,

會造成內存泄漏與數據混亂等等影響。


GC常用的回收算法

1,計數

引用計數是垃圾收集器中的早期策略。在這種方法中,堆中每個對象(不是引用)都有一個引用計數。

當一個對象被創建時,且將該對象分配給一個變量,該變量計數設置爲1。

當任何其它變量被賦值爲這個對象的引用時,計數加1(a = b,則b引用的對象+1),

但當一個對象的某個引用超過了生命週期或者被設置爲一個新值時,對象的引用計數減1。

任何引用計數爲0的對象可以被當作垃圾收集。當一個對象被垃圾收集時,它引用的任何對象計數減1。

優點:引用計數收集器可以很快的執行,交織在程序運行中。對程序不被長時間打斷的實時環境比較有利。


缺點: 無法檢測出循環引用。如父對象有一個對子對象的引用,子對象反過來引用父對象。

這樣,他們的引用計數永遠不可能爲0.


2,標記跟蹤

現在大多數JVM採用對象引用遍歷。對象引用遍歷從一組對象開始,沿着整個對象圖上的每條鏈接,

遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,

則將它作爲垃圾收集。在對象遍歷階段,GC必須記住哪些對象可以到達,以便刪除不可到達的對象,

這稱爲標記(marking)對象。

下一步,GC要刪除不可到達的對象。刪除時,有些GC只是簡單的掃描堆棧,

刪除未標記的未標記的對象,並釋放它們的內存以生成新的對象,這叫做清除(sweeping)。

這種方法的問題在於內存會分成好多小段,而它們不足以用於新的對象,但是組合起來卻很大。

因此,許多GC可以重新組織內存中的對象,並進行壓縮(compact),形成可利用的空間。


爲此,GC需要停止其他的活動活動。這種方法意味着所有與應用程序相關的工作停止,

只有GC運行。結果,在響應期間增減了許多混雜請求。

另外,更復雜的 GC不斷增加或同時運行以減少或者清除應用程序的中斷。

有的GC使用單線程完成這項工作,有的則採用多線程以增加效率。


3,在Java中還有很多收集器的算法,copiny,標記壓縮,增量等等。



GC回收過程


垃圾回收線程會從“根集(Root Set)”開始進行對象引用的遍歷。


所謂的“根集”,就是正在運行的線程中,可以訪問的引用變量 的 集合(比如所有線程當前函數的參數和局部變量、

當前類的成員變量等等)。


垃圾回收線程先找出被根集直接引用的所有對象(不妨叫集合1),


然後再找出被集合 1直接引用的所有對象(不妨叫集合2),


然後再找出被集合2直接引用的所有對象......如此循環往復,直到把能遍歷到的對象都遍歷完。


凡是從根集通過上述遍歷可以到達的對象,都稱爲可達對象或有效對象;

反之,則是不可達對象或失效對象(也就是垃圾)。


凡是從根集通過上述遍歷可以到達的對象,都稱爲可達對象或有效對象;

反之,則是不可達對象或失效對象(也就是垃圾)。




GC回收觸法原因

  • GC_CONCURRENT :當堆內存增長到一定程度時會觸發。此時觸發可以對堆中的沒有用的對象及時進行回收,騰出空間供新的對象申請,避免進行不必要的增大堆內存的操作。
  • GC_EXPLICIT :當程序中調用System.gc()方法觸發。這個方法應避免出現在程序中調用。因爲JVM有足夠的能力來控制垃圾回收。
  • GC_EXTERNAL_MALLOC :當Bitmap和NIO Direct ByteBuffer對象分配外部存儲(機器內存,非Dalvik堆內存)觸發。這個日誌只有在2.3之前存在,從2.3系統開始,垃圾回收進行了調整,前面的對象都會存儲到Dalivik堆內存中。所以在2.3系統之後,你就再也不會看到這種信息了。
  • GC_FOR_MALLOC  :當堆內存已滿,系統需要更多內存的時候觸發。這條日誌出現後意味着JVM要暫停你的程序進行垃圾回收操作。
  • GC_HPROF_DUMP_HEAP :當創建一個內存分析文件HPROF時觸發。

總結:既然GC去對內存進行回收爲什麼會有內存泄漏?


內存泄漏

內存泄漏也稱作“存儲滲漏”,用動態存儲分配函數動態開闢的空間,

在使用完畢後,GC並沒有進行對它回收(注意:GC是不會回收直接或間接地引用到gc roots的對象),

導致未釋放,結果導致一直佔據該內存單元。直到程序結束。

(其實說白了就是該內存空間使用完畢之後未回/收)即所謂內存泄漏。


補充Java內存泄漏指的是進程中某些對象(垃圾對象)已經沒有使用價值了,

但是它們卻可以直接或間接地引用到gc roots導致無法被GC回收。無用的對象佔據着內存空間,

使得實際可使用內存變小,形象地說法就是內存泄漏。


內存溢出

內存溢出(out of memory)通俗理解就是內存不夠,通常在運行大型軟件或遊戲時,

軟件或遊戲所需要的內存遠遠超出了你主機內安裝的內存所承受大小,就叫內存溢出。

此時軟件或遊戲就運行不了,系統會提示內存溢出,有時候會自動關閉軟件。

Android的虛擬機是基於寄存器的Dalvik,它的最大堆大小一般是16M,有的機器爲24M。

因此我們所能利用的內存空間是有限的。如果我們的內存佔用超過了一定的水平就會出現OutOfMemory的錯誤。


參照以下各位老兄的幸苦勞動:

Android中內存泄露的原因分析:

android GC內存回收小析

Android gc垃圾回收研究學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章