溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JVM的工作原理是什么

發(fā)布時(shí)間:2022-01-14 10:45:23 來源:億速云 閱讀:170 作者:小新 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)JVM的工作原理是什么,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

在JDK1.7及其以前我們所使用的都是Sun公司的HotSpot,但由于Sun公司和BEA公司都被oracle收購,jdk1.8將采用Sun公司的HotSpot和BEA公司的JRockit兩個(gè)JVM中精華形成jdk1.8的JVM。

 我們都知道java一直宣傳的口號(hào)是:一次編譯,到處運(yùn)行。那么它如何實(shí)現(xiàn)的呢?我們看下圖:

JVM的工作原理是什么

我們先看一段代碼:

public class HelloWorld { 
   public static void main(String[] args) { 
      System.out.print("Hello world"); 
   } 
}

這段程序從編譯到運(yùn)行,最終打印出“Hello world”中間經(jīng)過了哪些步驟呢?我們直接上圖:JVM的工作原理是什么

這里我們先不討論類加載的問題。

JVM的生命周期

1.啟動(dòng)。啟動(dòng)一個(gè)Java程序,一個(gè)JVM實(shí)例就產(chǎn)生。擁有public static void main(String[] args)函數(shù)的class可以作為JVM實(shí)例運(yùn)行的起點(diǎn)。

2.運(yùn)行。main()作為程序初始線程的起點(diǎn),任何其他線程均可由該線程啟動(dòng)。JVM內(nèi)部有兩種線程:守護(hù)線程和非守護(hù)線程,main()屬于非守護(hù)線程,守護(hù)線程通常由JVM使用,程序可以指定創(chuàng)建的線程為守護(hù)線程。

3.消亡。當(dāng)程序中的所有非守護(hù)線程都終止時(shí),JVM才退出;若安全管理器允許,程序也可以使用Runtime類或者System.exit()來退出。

JVM執(zhí)行引擎實(shí)例則對(duì)應(yīng)了屬于用戶運(yùn)行程序線程它是線程級(jí)別的。

JVM的體系結(jié)構(gòu)

JVM的工作原理是什么

JVM的數(shù)據(jù)運(yùn)行區(qū)

JVM調(diào)優(yōu)主要就是優(yōu)化 Heap堆 和 Method Area 方法區(qū)。

JVM的工作原理是什么

Method Area方法區(qū)

方法區(qū)是被所有線程共享,所有字段和方法字節(jié)碼,以及一些特殊方法如構(gòu)造函數(shù),接口代碼也在此定義。簡(jiǎn)單說,所有定義的方法的信息都保存在該區(qū)域,此區(qū)域?qū)儆诠蚕韰^(qū)間。

靜態(tài)變量+常量+類信息+運(yùn)行時(shí)常量池存在方法區(qū)中,實(shí)例變量存在堆內(nèi)存中。

Stack 棧

棧中的數(shù)據(jù)都是以棧幀(Stack Frame)的格式存在,棧幀是一個(gè)內(nèi)存區(qū)塊,是一個(gè)數(shù)據(jù)集,是一個(gè)有關(guān)方法和運(yùn)行期數(shù)據(jù)的數(shù)據(jù)集,當(dāng)一個(gè)方法A被調(diào)用時(shí)就產(chǎn)生了一個(gè)棧幀F(xiàn)1,并被壓入到棧中,A方法又調(diào)用了B方法,于是產(chǎn)生棧幀F(xiàn)2也被壓入棧,B方法又調(diào)用了C方法,于是產(chǎn)生棧幀F(xiàn)3也被壓入?!?依次執(zhí)行完畢后,先彈出后進(jìn)......F3棧幀,再彈出F2棧幀,再彈出F1棧幀。

遵循“先進(jìn)后出”/“后進(jìn)先出”原則。

Heap 堆

堆這塊區(qū)域是JVM中最大的,應(yīng)用的對(duì)象和數(shù)據(jù)都是存在這個(gè)區(qū)域,這塊區(qū)域也是線程共享的,也是 gc 主要的回收區(qū),一個(gè) JVM 實(shí)例只存在一個(gè)堆類存,堆內(nèi)存的大小是可以調(diào)節(jié)的。類加載器讀取了類文件后,需要把類、方法、常變量放到堆內(nèi)存中,以方便執(zhí)行器執(zhí)行,堆內(nèi)存分為三部分:

JVM的工作原理是什么

① 新生區(qū)

新生區(qū)是類的誕生、成長(zhǎng)、消亡的區(qū)域,一個(gè)類在這里產(chǎn)生,應(yīng)用,最后被垃圾回收器收集,結(jié)束生命。新生區(qū)又分為兩部分:伊甸區(qū)(Eden space)和幸存者區(qū)(Survivor pace),所有的類都是在伊甸區(qū)被new出來的。幸存區(qū)有兩個(gè):0區(qū)(Survivor 0 space)和1區(qū)(Survivor 1 space)。當(dāng)伊甸園的空間用完時(shí),程序又需要?jiǎng)?chuàng)建對(duì)象,JVM的垃圾回收器將對(duì)伊甸園進(jìn)行垃圾回收(Minor GC),將伊甸園中的剩余對(duì)象移動(dòng)到幸存0區(qū)。若幸存0區(qū)也滿了,再對(duì)該區(qū)進(jìn)行垃圾回收,然后移動(dòng)到1區(qū)。那如果1去也滿了呢?再移動(dòng)到養(yǎng)老區(qū)。若養(yǎng)老區(qū)也滿了,那么這個(gè)時(shí)候?qū)a(chǎn)生Major GC(FullGCC),進(jìn)行養(yǎng)老區(qū)的內(nèi)存清理。若養(yǎng)老區(qū)執(zhí)行Full GC 之后發(fā)現(xiàn)依然無法進(jìn)行對(duì)象的保存,就會(huì)產(chǎn)生OOM異常“OutOfMemoryError”。

如果出現(xiàn)java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機(jī)的堆內(nèi)存不夠。原因有二:

a.Java虛擬機(jī)的堆內(nèi)存設(shè)置不夠,可以通過參數(shù)-Xms、-Xmx來調(diào)整。

b.代碼中創(chuàng)建了大量大對(duì)象,并且長(zhǎng)時(shí)間不能被垃圾收集器收集(存在被引用)。

② 養(yǎng)老區(qū)

養(yǎng)老區(qū)用于保存從新生區(qū)篩選出來的 JAVA 對(duì)象,一般池對(duì)象都在這個(gè)區(qū)域活躍。

③ 永久區(qū)

永久存儲(chǔ)區(qū)是一個(gè)常駐內(nèi)存區(qū)域,用于存放JDK自身所攜帶的 Class,Interface 的元數(shù)據(jù),也就是說它存儲(chǔ)的是運(yùn)行環(huán)境必須的類信息,被裝載進(jìn)此區(qū)域的數(shù)據(jù)是不會(huì)被垃圾回收器回收掉的,關(guān)閉 JVM 才會(huì)釋放此區(qū)域所占用的內(nèi)存。

如果出現(xiàn)java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機(jī)對(duì)永久代Perm內(nèi)存設(shè)置不夠。原因有二:

a. 程序啟動(dòng)需要加載大量的第三方j(luò)ar包。例如:在一個(gè)Tomcat下部署了太多的應(yīng)用。

b. 大量動(dòng)態(tài)反射生成的類不斷被加載,最終導(dǎo)致Perm區(qū)被占滿。

JVM垃圾回收

(一)引用計(jì)數(shù)(Reference Counting):

比較古老的回收算法。原理是此對(duì)象有一個(gè)引用,即增加一個(gè)計(jì)數(shù),刪除一個(gè)引用則減少一個(gè)計(jì)數(shù)。垃圾回收時(shí),只用收集計(jì)數(shù)為0的對(duì)象。此算法最致命的是無法處理循環(huán)引用的問題。

(二)標(biāo)記-清除(Mark-Sweep):

JVM的工作原理是什么

 此算法執(zhí)行分兩階段。第一階段從引用根節(jié)點(diǎn)開始標(biāo)記所有被引用的對(duì)象,第二階段遍歷整個(gè)堆,把未標(biāo)記的對(duì)象清除。此算法需要暫停整個(gè)應(yīng)用,同時(shí),會(huì)產(chǎn)生內(nèi)存碎片。

(三)復(fù)制(Copying):

JVM的工作原理是什么

 此算法把內(nèi)存空間劃為兩個(gè)相等的區(qū)域,每次只使用其中一個(gè)區(qū)域。垃圾回收時(shí),遍歷當(dāng)前使用區(qū)域,把正在使用中的對(duì)象復(fù)制到另外一個(gè)區(qū)域中。算法每次只處理正在使用中的對(duì)象,因此復(fù)制成本比較小,同時(shí)復(fù)制過去以后還能進(jìn)行相應(yīng)的內(nèi)存整理,不會(huì)出現(xiàn)“碎片”問題。當(dāng)然,此算法的缺點(diǎn)也是很明顯的,就是需要兩倍內(nèi)存空間。

(四)標(biāo)記-整理(Mark-Compact):

JVM的工作原理是什么

  此算法結(jié)合了“標(biāo)記-清除”和“復(fù)制”兩個(gè)算法的優(yōu)點(diǎn)。也是分兩階段,第一階段從根節(jié)點(diǎn)開始標(biāo)記所有被引用對(duì)象,第二階段遍歷整個(gè)堆,清除未標(biāo)記對(duì)象并且把存活對(duì)象“壓縮”到堆的其中一塊,按順序排放。此算法避免了“標(biāo)記-清除”的碎片問題,同時(shí)也避免了“復(fù)制”算法的空間問題。

關(guān)于“JVM的工作原理是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI