Android 面試系統(tǒng)復(fù)習(xí)系列(三)Java 虛擬機原理

Android 面試系統(tǒng)復(fù)習(xí)系列(三)Java 虛擬機原理

運行時數(shù)據(jù)區(qū)

程序計數(shù)器(線程私有)

它可以看做當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。

虛擬機棧(線程私有)

虛擬機棧描述的是 Java 方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀,用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。每一個方法從調(diào)用到執(zhí)行完成的過程,就對應(yīng)著一個棧幀再虛擬機棧中入棧到出棧的過程。

本地方法棧(線程私有)

同虛擬機棧,區(qū)別就是虛擬機棧執(zhí)行的是 Java 方法,本地方法棧執(zhí)行的是 Native 的方法。

Java 堆(線程共享)

存放對象實例,幾乎所有對象實例都在這里分配內(nèi)存,也是垃圾收集器管理的主要區(qū)域。

方法區(qū)(線程共享)

存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、及時編譯器編譯后的代碼等數(shù)據(jù)。

垃圾回收機制

Java 虛擬機如何判斷一個對象可以回收

有兩種主流算法,一種是引用計數(shù)法,給對象添加一個引用計數(shù)器,每當(dāng)有一個地方引用它時,計數(shù)器加一,引用失效時計數(shù)器減一。

這種算法簡單高效,但是卻避免不了互相循環(huán)引用無法回收的問題,所以 Java 虛擬機并沒有采用這種算法。

所以我們 Java 虛擬機采用的是第二種算法,可達性分析算法。

這個算法的基本思路就是通過一系列的成為“GC Roots”的對象作為七點,從這些節(jié)點開始向下搜索,搜索走過的路徑稱為引用鏈,當(dāng)一個對象到 GC Roots沒有任何引用鏈相連時,則證明此對象是不可達的,所以會被虛擬機判定為可回收的對象。

可作為 GC Roots 的對象

  • 虛擬機棧中引用的對象
  • 方法去中類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧中 JNI 引用的對象

垃圾回收算法

標記-清除算法

最基礎(chǔ)的垃圾回收算法,先標記出所有需要回收的對象,在標記完成后統(tǒng)一回收所有被標記的對象。

優(yōu)點:實現(xiàn)簡單

缺點:一、效率低,標記和清除兩個過程效率都不高。二、回收后可能產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會導(dǎo)致以后在分配大內(nèi)存對象時,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集。

復(fù)制算法

將內(nèi)存按容量劃分為大小相同的兩塊,然后每次只使用其中的一塊。當(dāng)一塊內(nèi)容用完了,就將還存活的對象移動到另一塊,然后再將之前使用的內(nèi)存空間一次性清理掉。

優(yōu)點:實現(xiàn)簡單,運行高效

缺點:會將可用內(nèi)存縮小為原來的一半,對象存活率高的話,效率會變低

現(xiàn)在商業(yè)虛擬機在回收新生代區(qū)域的時候都會采用這種算法,不過由于新生代里的對象絕大部分都是“朝生夕死”,所以并不需要按照 1:1 的比例來劃分內(nèi)存空間,HotSpot 虛擬機默認比例是 8:1,所以空閑出來的內(nèi)存空間很小。不過在存活對象大于剩余的空間時,會向老年代進行分配擔(dān)保,直接進入老年代。

標記-整理算法

標記的過程同標記-清除算法的標記過程,不過后續(xù)不是直接對可回收對象進行清理,而是讓所有存活對象都向一端移動,然后再清理邊界外的內(nèi)存。

老年代因為對象存活率高,沒有額外空間對它分配擔(dān)保,所以一般使用標記-清理或者標記-整理算法進行回收。

分代回收算法

當(dāng)前商業(yè)虛擬機的路基手機都采用這種算法,并沒有什么新的思想,只是根據(jù)對象的存活周期的不同,將內(nèi)存分為幾塊,一般是新生代,老年代,然后再根據(jù)其區(qū)域的特點,采用不同的垃圾收集算法進行回收。

Dalvik 虛擬機和 JVM 的區(qū)別

掘金上這篇文章寫得很清晰 https://juejin.im/post/59b7fa8cf265da066d3323bb

這里摘幾點主要的記一下:

  • Dalvik 基于寄存器,基于寄存器的虛擬機雖然比基于堆棧的虛擬機在硬件,通用性上要差一些,但是它的代碼執(zhí)行效率去更好
  • JVM 基于棧
  • Dalvik虛擬機運行的是其專有的文件格式Dex
  • JVM 運行 java 字節(jié)碼

ART 虛擬機

ART 的機制與 Dalvik 不同。在Dalvik下,應(yīng)用每次運行的時候,字節(jié)碼都需要通過即時編譯器(just in time ,JIT)轉(zhuǎn)換為機器碼,這會拖慢應(yīng)用的運行效率,而在ART 環(huán)境中,應(yīng)用在第一次安裝的時候,字節(jié)碼就會預(yù)先編譯成機器碼,使其成為真正的本地應(yīng)用。這個過程叫做預(yù)編譯(AOT,Ahead-Of-Time)。這樣的話,應(yīng)用的啟動(首次)和執(zhí)行都會變得更加快速。

缺點

1.機器碼占用的存儲空間更大,字節(jié)碼變?yōu)闄C器碼之后,可能會增加10%-20%(不過在應(yīng)用包中,可執(zhí)行的代碼常常只是一部分。比如最新的 Google+ APK 是 28.3 MB,但是代碼只有 6.9 MB。)

2.應(yīng)用的安裝時間會變長。

每個小標題都可作為面試題,故本篇沒有精心挑選的面試題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容