熱修復與插件化基礎——Java與Android虛擬機

1、Java虛擬機(JVM)

一、JVM總體結構

  1. 使用javac將java文件編譯成class文件。
  2. 類加載器(ClassLoader)將class字節碼加載進JVM對應的內存中。
  3. JVM將內存分配給方法區、堆區、棧區、本地方式棧4個部分,這4個部分分別存儲字節碼不一樣的部分。
  4. 垃圾回收器(gc)會管理整個內存空間中的垃圾。

二、Java代碼的編譯和執行過程

下圖是Java代碼編譯的詳細流程(即,javac的執行過程),瞭解便可,通常只要知道java文件是經過javac命令編譯成class文件,再經過java命令運行的就能夠了,如:java

javac Hello.java
java Hello
複製代碼

三、類加載器

1)Java中的類加載器

2)加載流程

  • Loading:類的信息從文件中獲取並載入到JVM的內存中。
  • Verifying:檢查讀入的結構是否符合JVM規範的描述。
  • Preparing:分配一個結構用來存儲類信息。
  • Resolving:把類的常量池中的全部符號引用變成直接引用。
  • Initializing:執行靜態初始化程序,把靜態變量初始化成指定的值。

四、內存管理

java中的內存管理指的是下圖中「內存空間」部分的內存操做。算法

1)Java棧區:

做用:存放java方法執行時全部的數據。 組成:由棧幀組成,一個棧幀表明一個方法的執行。spa

Java棧幀:每一個方法從調用到執行完成就對應一個棧幀在虛擬機棧中入棧到出棧。它描述了一個方法的局部變量表、棧操做數、動態連接、方法出口。線程

2)本地方法棧

與Java棧區基於一致。指針

做用:本地方法棧是專門爲native方法服務的。code

3)方法區

存儲被虛擬機加載的類信息、常量、靜態常量、即時編譯器編譯後等數據(這些數據在程序啓動後會永遠佔據內存)。cdn

4)堆區

做用:全部經過new建立的對象的內存都在堆中分配。 特色:是虛擬機中最大的一塊內存,是GC要回收的部分。對象

對於堆區,其內存結構還有些不同的地方,先看下圖:blog

簡單來講,堆區分爲新生代(Young Generation)與老年代(Old Generation),程序在創始對象時,對象會先被分配到新生代中,當新生代區內存不足時,JVM會經過必定的算法規則將新生代中的對象轉移至老年代中,當新生代與老年代都沒有足夠的內存空間時,JVM就會拋出OOM異常。內存

五、垃圾回收

一、垃圾收集算法

1)引用記數算法(jdk1.2以前)

在內存建立對象的同時,會爲它建立一個引用記數器,並將引用記數器加1,每次有引用引用到此對象時,記數器就會累計加1,而當其中一個引用銷燬時,記數器就會減1,當引用記數器爲0時,說明該對象已是垃圾對象,下次gc時,對象就會被回收了。

弊端: 對象A與對象B互相引用時,這2個對象的引用記數器永遠是正數,當這2個對象都沒有被其餘對象所引用時(對象不可達),會由於它們的引用記數器不爲0致使它們不會被gc回收。

2)可達性算法(jdk1.2 +)

也稱爲根搜索算法。把程序全部的引用關係看作是一張圖(有向圖),從GC Root節點開始尋找全部的引用節點,當全部的引用節點尋找完畢以後,剩餘的節點被認爲是沒有引用的節點,即不可達的節點,就是垃圾對象。

上圖中ObjD、E、F由於沒有路徑可達,因此是垃圾對象。

二、引用的類型

java中的引用類型有4種:強引用、軟引用、弱引用、虛引用。其中,強引用和弱引用在開發中最經常使用。

弱引用的建立

// 強引用
Object obj = new Object();
// 弱引用,此時obj與wf都引用了Object對象
WeakReference<Object> wf = new WeakReference<Object>(obj);
// 斷開強引用,此時只有wf引用這個Object對象
obj = null;
// 通用弱引用獲取Object對象(可能爲null)
wf.get();
複製代碼

在使用wf.get()時,要判斷獲取到的對象是否爲null,由於弱引用不會阻止對象的回收。

三、垃圾回收算法

1)標記-清除算法

從根集合遍歷全部的引用,上圖中,根集合引用了A,A引用了C,B是不可達的對象引用,在掃描階段中,B會被標記爲垃圾對象,當垃圾回收機制執行時,會直接將B對象置爲空,此時內存塊中就只剩下A、C對象引用,B就被垃圾回收給回收掉了。 優勢:不須要進行對象的移動,僅對不存活的對象進行處理,在存活對象比較多的狀況下極爲高效。 缺點:因爲標記-清除算法會直接回收掉不存活的對象,會形成內在碎片,不利於後續對象的分配

2)複製算法

從根集合開始遍歷,上圖中,遍歷到A時是可達的,就把A複製到另外一塊空閒的內存中,繼續遍歷,發現B不可達,直接跳過,日後,發現C可達,就把C一樣地複製到這塊空閒內存中,等全部複製都處理完時,把原來的內存空間清空,只保留複製後的這塊內存空間。 優勢:當存活對象比較少時,極爲高效,且不會有產生內存碎片。 缺點:須要一塊內存做爲交換空間來進行對象的移動。

3)標記-整理算法

從根集合開始遍歷,經過對整個內存區的掃描,將可回收對象掃描出來,上圖中,到了第二階段,就將B標記爲可回收對象,到了第三個階段,直接掃描並消除內存中被標記的對象,同時,在回收不存活對象佔用的空間時,會將內存中全部存活對象往左端空閒處移動,並更新對應的指針。

這三種算法各有優劣,JVM在處理垃圾時會整合去使用,並非只使用其中某個算法。當內存中存活的對象比較少時,採用「複製算法」去處理垃圾對象;當內存中存活的對象比較多時,會採用「標記-整理算法」或「標記-清除算法」去處理垃圾對象。

四、觸發回收

  • Java虛擬機沒法再爲新對象分配內存空間了
  • 手動調用System.gc()方法(強烈不推薦,不會立刻執行,卻會加大虛擬機壓力)
  • 低優先級的GC線程,被啓動了。

2、Android 虛擬機

一、Dalvik VM 與 JVM 的不一樣

  • 執行的文件不一樣,一個是class,一個是dex。
  • 類加載的系統與JVM區別較大。
  • 能夠同時存在多個DVM,但JVM只能存在一個。
  • Dalvik是基於寄存器的,而JVM是基於棧的。

二、Dalvik VM 與 ART 的不一樣

  • DVM使用JIT來將字節碼轉換成機器碼,效率低。
  • ART採用了AOT預編譯技術,執行速度更快。
  • ART會佔用更多的應用安裝時間和存儲空間。
相關文章
相關標籤/搜索