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

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

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

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

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

虛擬機(jī)棧(線程私有)

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

本地方法棧(線程私有)

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

Java 堆(線程共享)

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

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

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

垃圾回收機(jī)制

Java 虛擬機(jī)如何判斷一個(gè)對(duì)象可以回收

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

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

所以我們 Java 虛擬機(jī)采用的是第二種算法,可達(dá)性分析算法

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

可作為 GC Roots 的對(duì)象

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

垃圾回收算法

標(biāo)記-清除算法

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

優(yōu)點(diǎn):實(shí)現(xiàn)簡單

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

復(fù)制算法

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

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

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

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

標(biāo)記-整理算法

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

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

分代回收算法

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

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

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

這里摘幾點(diǎn)主要的記一下:

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

ART 虛擬機(jī)

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

缺點(diǎn)

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

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

每個(gè)小標(biāo)題都可作為面試題,故本篇沒有精心挑選的面試題

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

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

  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,484評(píng)論 1 34
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,300評(píng)論 0 2
  • 1.1 概述 Java優(yōu)點(diǎn): 1、結(jié)構(gòu)嚴(yán)謹(jǐn),面向?qū)ο?2、擺脫硬件平臺(tái)束縛,實(shí)現(xiàn)了“一次編寫,到處運(yùn)行”的理想; ...
    viciyforever閱讀 1,343評(píng)論 1 9
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器,...
    luhanlin閱讀 615評(píng)論 0 0
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器,...
    加油小杜閱讀 1,589評(píng)論 1 15

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