尊重個人勞動成果,轉載請注明出處:http://blog.csdn.net/hnulwt/article/details/44903331
文中很多內容說到了JVM,我想通過研究學習JVM來到達認識DVM的目的。為了嚴謹,查詢了1下
Dalvik 基于寄存器,而 JVM 基于棧?;诩拇嫫鞯奶摂M機對更大的程序來講,在它們編譯的時候,花費的時間更短。
Dalvik履行.dex格式的字節碼,而JVM履行.class格式的字節碼。android程序編譯完以后生產.class文件,還有通過aapt工具生成的R.class等,然后dx工具會把.class文件處理成.dex文件,終究資源文件和.dex文件等打包成.apk文件。
Dalvik主要是完成對象生命周期管理,堆棧管理,線程管理,安全和異常管理,和垃圾回收等等重要功能。
Dalvik負責進程隔離和線程管理,每個Android利用在底層都會對應1個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以履行。
通過以上可以看出,這些不同點其實不影響對DVM―gc相干的學習,所以我通過研究JVM相干的垃圾回收機制,來學習Android gc相干內容,如果文中有甚么不對的地方,麻煩大家指出,共同學習,共同進步。
粗略的說:GC(Garbage Collection)動態回收無任何援用的對象占據的內存空間。GC通過肯定對象是不是被活動對象援用來肯定是不是搜集該對象。
但是理解以上幾句話我們可能需要了解以下知識。
圖中的Eden + S0 + S1
Eden:寄存新生的對象
Survivor Space:S0、S1 有兩個,寄存每次垃圾回收后存活的對象
(1)大多數新建的對象都位于Eden區。
(2)當Eden區被對象填滿時,就會履行Minor GC。并把所有存活下來的對象轉移到其中1個survivor區。
(3)Minor GC一樣會檢查存活下來的對象,并把它們轉移到另外一個survivor區。這樣在1段時間內,總會有1個空的survivor區。
圖中的Old Memory 主要寄存利用程序中 長時間存活的對象和經過量次Minor GC后仍然存活下來的對象。通常會在老年代內存被占滿時進行垃圾回收。老年代的垃圾搜集叫做Major GC。Major GC會花費更多的時間。
寄存方法區,方法區中有 要加載的類信息、靜態變量、final類型的常量、屬性和方法信息。
新生代通常存活時間較短,因此基于Copying算法來進行回收,所謂Copying算法就是掃描出存活的對象,并復制到1塊新的完全未使用的空間中,對應于新生代,就是在Eden和FromSpace或ToSpace之間copy。新生代采取空閑指針的方式來控制GC觸發,指針保持最后1個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用于檢查空間是不是足夠,不夠就觸發GC。當連續分配對象時,對象會逐步從eden到survivor,最后到舊生代。
舊生代與新生代不同,對象存活的時間比較長,比較穩定,因此采取標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,然后再進行回收未被標記的對象,回收后對用空出的空間要末進行合并,要末標記出來便于下次進行分配,總之就是要減少內存碎片帶來的效力消耗。
兩種經常使用的方法是援用計數和對象援用遍歷。
援用計數是垃圾搜集器中的初期策略。在這類方法中,堆中每一個對象(不是援用)都有1個援用計數。當1個對象被創建時,且將該對象分配給1個變量,該變量計數設置為1。當任何其它變量被賦值為這個對象的援用時,計數加1(a = b,則b援用的對象+1),但當1個對象的某個援用超過了生命周期或被設置為1個新值時,對象的援用計數減1。任何援用計數為0的對象可以被當作垃圾搜集。當1個對象被垃圾搜集時,它援用的任何對象計數減1。
優點:援用計數搜集器可以很快的履行,交織在程序運行中。對程序不被長時間打斷的實時環境比較有益。
缺點: 沒法檢測出循環援用。如父對象有1個對子對象的援用,子對象反過來援用父對象。這樣,他們的援用計數永久不可能為0.
現在大多數JVM采取對象援用遍歷。對象援用遍歷從1組對象開始,沿著全部對象圖上的每條鏈接,遞歸肯定可到達(reachable)的對象。如果某對象不能從這些根對象的1個(最少1個)到達,則將它作為垃圾搜集。在對象遍歷階段,GC必須記住哪些對象可以到達,以便刪除不可到達的對象,這稱為標記(marking)對象。
下1步,GC要刪除不可到達的對象。刪除時,有些GC只是簡單的掃描堆棧,刪除未標記的未標記的對象,并釋放它們的內存以生成新的對象,這叫做清除(sweeping)。這類方法的問題在于內存會分成好多小段,而它們不足以用于新的對象,但是組合起來卻很大。因此,許多GC可以重新組織內存中的對象,并進行緊縮(compact),構成可利用的空間。
為此,GC需要停止其他的活動活動。這類方法意味著所有與利用程序相干的工作停止,只有GC運行。結果,在響應期間增減了許多混雜要求。另外,更復雜的 GC不斷增加或同時運行以減少或清除利用程序的中斷。有的GC使用單線程完成這項工作,有的則采取多線程以增加效力。
在官方文檔上查了1下,gc reason有以下5個:
GC_CONCURRENT
A concurrent garbage collection that frees up memory as your heap begins to fill up.
GC_FOR_MALLOC
A garbage collection caused because your app attempted to allocate memory when your heap was already full, so the system had to stop your app and reclaim memory.
GC_HPROF_DUMP_HEAP
A garbage collection that occurs when you create an HPROF file to analyze your heap.
GC_EXPLICIT
An explicit garbage collection, such as when you call gc() (which you should avoid calling and instead trust the garbage collector to run when needed).
GC_EXTERNAL_ALLOC
This happens only on API level 10 and lower (newer versions allocate everything in the Dalvik heap). A garbage collection for externally allocated memory (such as the pixel data stored in native memory or NIO byte buffers).
GC_CONCURRENT、GC_FOR_MALLOC都是比較常見的gc緣由。可以通過運行程序在Logcat上查看。
GC_CONCURRENT當堆要滿的時候進行的垃圾搜集
GC_FOR_MALLOC這就是“Stop the World”事件,由于所有的利用線程都會停下來直到操作完成。這時候候堆已滿了,你申請分配內存就會觸發這類緣由的gc。
GC_HPROF_DUMP_HEAP
在我們創建HPROF文件分析堆內存的時候的gc緣由。
GC_EXPLICIT
當我們顯示的調用System.gc()方法,會出現的log。
GC_EXTERNAL_ALLOC
這個僅僅在API 10 及以下才會出現,我們不需要關注了。
文章部份參考自:
原文鏈接: journaldev 翻譯: ImportNew.com - 進林 譯文鏈接: http://www.importnew.com/14086.html
詳細介紹Java垃圾回收機制:http://www.cnblogs.com/laoyangHJ/articles/java_gc.html
百度百科:http://baike.baidu.com/view/1551869.htm