從Java垃圾回收機制窺探內存優化(加強版)

前言

其實這篇文章幾個月以前已經發布到簡書博客裏了,可是文章發佈以後,有人反饋了一些問題,而我對於這篇文章也有刪改增補的想法,因此這篇文章會是原文的簡潔加強版python

回答一個疑問

這篇文章講的是Java的JVM的垃圾回收機制,可是Android使用的虛擬機是Dalvik或者ART,那麼下面講的垃圾回收機制是否適用於Android呢?android

答案是,Yes,是能夠類比的。算法

增補
文章末尾有人提出了質疑: JVM 的內存模型和 Android 虛擬機是區別的?網絡

答案:是的,Android基於寄存器,jvm基於堆棧,本文其實避免了這樣的探討,那是由於在邏輯上它們其實沒有太大區別,Android做爲移動操做系統基於寄存器,能夠極大提升它的訪存速度,從而提升它的程序運行速度,堆棧訪存就慢些。這是最大的區別,在這裏作出說明。多線程

其餘的問題我也在評論裏作出了迴應,有任何問題均可以在下面探討,若是本文有重大漏洞,我會卸載勘誤
一欄中,你們能夠關注一下。jvm


開始

做爲Android工程師,我看過不少關於Android內存泄漏的相關優化的文章,其中大部分都是告訴你該怎麼作,作哪些,列一些具體的措施。不多解釋爲何要這麼作,即便解釋,也只是一筆帶過。post

今天,我就之內存回收爲突破口,向你們解釋從底層到上層,是如何配合完成內存回收的。咱們就從Java程序運行時的內存區域開始吧。優化

運行時內存區域,指的是當你的程序被JVM加載進來執行的時候,內存是怎麼分配的。spa

下面,就是Java程序運行時的內存模型操作系統

  • 如上圖所示,當你的Java字節碼執行起來的時候,虛擬機就會它所管理的內存大體分紅這五個部分,把你的代碼,產生的對象等等分別扔到這五個框框裏:
    • 方法區:用於存儲類信息,常量,靜態變量,編譯後的代碼等等這些
    • 本地方法棧:用於爲本地方法的執行提供服務(能夠不瞭解)
    • 虛擬機棧:是虛擬機執行Java方法的重要內存模型。內部有一個局部變量表,這個表存儲了對象引用(這個局部變量表常被咱們成爲棧)。
    • 堆:存儲對象實例的區域(好比 A a=new A(),那麼 a這個引用就保存在上面的局部變量表中,而new A() 的這個對象就放在堆中
    • 程序計數器:用來記錄當前線程執行的字節碼的地址,指示執行引擎執行代碼。
      執行引擎:哎呀臥槽,剛纔執行到哪一步來着?
       程序計數器:傻逼。複製代碼

其實上面那五個區域,和這篇文章關係最緊密的時虛擬機棧中的局部變量表(也就是咱們常說的棧),棧中主要保存了對象的引用,堆中保存了實際的對象,所以,實際上堆佔了整個程序運行內存的大頭,所以,內存回收就發生在堆中。

當程序運行時,而後躲在暗處的那個飢渴難耐端的垃圾回收機制(GC)就立刻跳出來了。虎視眈眈的盯着堆中的對象,專門找那些「落單」的對象....

那麼,GC是怎麼知道哪一個對象「落單」了呢,答案是GC Roots引用鏈。

  • 經過這個引用鏈往下搜索,全部在這些鏈條上的對象都拿到了免死金牌,而其他就是落單的,它們隨後就會被GC回收。

關於GC引用鏈不管怎麼說,都很難想象,那不要緊,我來畫一畫就行了。

  • GC程序從棧頂開始一直找到棧底,尋找每一個對象引用所對應的對象實例,而後在實例中尋找是否有指向其餘對象的引用,如有,繼續找(這一部分並無畫出,可是也是重點),沒有,則回到棧中,繼續往棧底搜索。
  • 固然,GC不止會在棧中尋找引用,還會在靜態存儲區(存儲靜態變量的信息存儲在方法區)中尋找引用,(由於有的堆中的對象在棧中沒有引用,它的引用在靜態存儲區,相似於 static A a =new A() )

當那些待回收的對象被標記以後,GC就會開始回收對象釋放內存。GC的回收算法有不少種,通常虛擬機配合多種內存回收算法來實現內存的高效回收,可是這些和咱們其實關係不大,所以能夠略過。

好了,咱們終於把Java內存回收的機理講完了,那麼內存優化背後的機理也基本被咱們扒開了:

  • 再也不使用對象時,將引用置空,那麼GC順着棧或者靜態存儲區中的引用就找不到堆中對應的對象,那麼這個對應的對象就會被回收。
  • 儘可能不要在生命週期較長(程序執行期間可能都不會被收回)的對象實例中引用其餘的沒必要要的佔內存較大的對象實例

不少Android優化場景,基本圍繞了一個點:

  • Android中Activity,context,bitmap等佔據較大的內存空間對象,在不用的時候,必定保證當前對象的直接引用和間接引用所有被置爲空。內存才能被釋放。(重點注意多線程和網絡請求這種不可控的場景)

因此Java內存優化一個最根本的準則,就是努力使你的程序適配Java的GC機制

後記

最近下定決心要涉足新領域,所以給本身定下目標,從這一篇開始,要系統的概括本身所學的知識技術以及積攢的經驗,以文章的方式產出。內容主要以Java+Android相關爲主,以JS+React-native次之,而後是一些基於python的有意思的項目(是大學裏寫的,會從新整理)。

你們放心,個人文章會保證一向的簡單友好,至少同一個層次的知識,個人文章能比別人更加友好,我有這樣的信心。

回到這篇文章自己,其實在從新整理的時候,我已經發現最近掘金上已經有人把Android優化整理了一個系列文章,我以爲寫的很不錯,在這裏也能夠推薦給你們@anly_jun: android優化系列

固然,若是你比較欣賞個人文章風格,歡迎關注我,我會在保證文章質量的前提下,提升寫做速度的。

共勉

勘誤

暫無

參考

《深刻理解Java虛擬機》

相關文章
相關標籤/搜索