www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]簡介 JVM也叫Java Virtual Machine,它是java程序運行的基礎(chǔ),負(fù)責(zé)將java bytecode轉(zhuǎn)換成為適合在各個不同操作系統(tǒng)中運行的機(jī)器代碼并運行。 今天我們和小師妹一起走進(jìn)java的核心JVM,領(lǐng)略JVM在設(shè)計上的哲學(xué)。 JVM是一種標(biāo)準(zhǔn) 小師妹:F師兄,經(jīng)常聽到有人說hots

JVM的架構(gòu)和執(zhí)行過程




簡介


JVM也叫Java Virtual Machine,它是java程序運行的基礎(chǔ),負(fù)責(zé)將java bytecode轉(zhuǎn)換成為適合在各個不同操作系統(tǒng)中運行的機(jī)器代碼并運行。


今天我們和小師妹一起走進(jìn)java的核心JVM,領(lǐng)略JVM在設(shè)計上的哲學(xué)。



JVM是一種標(biāo)準(zhǔn)


小師妹:F師兄,經(jīng)常聽到有人說hotspot VM,這個跟JVM是什么關(guān)系?


其實吧,JVM只是一種標(biāo)準(zhǔn),就像是一種協(xié)議,只要是實現(xiàn)和滿足這種協(xié)議的都可以稱為JVM。


當(dāng)然,java現(xiàn)在是Oracle公司的,所以這些所謂的JVM標(biāo)準(zhǔn)也是由Oracle來頒布的,如果你去查看Oracle的文檔,就會發(fā)現(xiàn)有一個專門的Java SE Specifications欄目,這個欄目中列出了JVM的實現(xiàn)標(biāo)準(zhǔn),最新的標(biāo)準(zhǔn)就是The Java Virtual Machine Specification, Java SE 14 Edition。


既然JVM是一個標(biāo)準(zhǔn),就可能有很多種實現(xiàn)。各大公司在滿足JVM標(biāo)準(zhǔn)的基礎(chǔ)上,開發(fā)了很多個不同的版本。


下面是我在維基百科中截取到的目前各個JVM的比較:

JVM的架構(gòu)和執(zhí)行過程


小師妹:F師兄,大家齊心協(xié)力做一個JVM不是更好嗎?為什么分來分去的,還要重復(fù)造輪子?


有聽過Oracle和Google之間的API十年訴訟案嗎?API都不能隨便用,更何況是JVM。各大廠商為了各自的利益,最終搞出了這么多個JVM的版本。


在這些JVM中,最常用的就是HotSpot JVM了,畢竟它是Oracle的親兒子,或者可以說HotSpot JVM就是JVM的標(biāo)準(zhǔn)。


接下來就是Eclipse OpenJ9,這個是由IBM主導(dǎo)的JVM,一般只能跟IBM的產(chǎn)品一起使用的,因為有許可證限制。



java程序的執(zhí)行順序


為了說明JVM的作用,我們先來回顧一下java程序的執(zhí)行順序。

JVM的架構(gòu)和執(zhí)行過程


  1. 編寫java代碼文件比如Example.java

  2. 使用java編譯器javac將源文件編譯成為Example.class文件

  3. JVM加載生成的字節(jié)碼文件,將其轉(zhuǎn)換成為機(jī)器可以識別的native machine code執(zhí)行



JVM的架構(gòu)


小師妹:F師兄,Java語言那么多特性,最后都要在JVM中運行,JVM的架構(gòu)是不是特別復(fù)雜?好怕我聽不懂。


其實吧,JVM可以分為三大部分,五大空間和三大引擎,要講起來也不是特別復(fù)雜,先看下面的總體的JVM架構(gòu)圖。

JVM的架構(gòu)和執(zhí)行過程


從上面的圖中,我們可以看到JVM中有三大部分,分別是類加載系統(tǒng),運行時數(shù)據(jù)區(qū)域和Execution Engine。

01

類加載系統(tǒng)

類加載系統(tǒng)分為三個階段,分別是加載,鏈接和初始化。


加載大家都很清楚了,java中有個專門的ClassLoader來負(fù)責(zé)這個事情。除了加載Class之外,ClassLoader還可以用來加載resources。


在JDK9之前,系統(tǒng)默認(rèn)有三個類加載器,分別是:

1. Bootstrap ClassLoader


這個類加載器主要是加載 /jre/lib下面的rt.jar,并且這個類加載器是用C/C++來編寫的,并且它是后面Extension ClassLoader的父ClassLoader。


這個類應(yīng)該在java代碼中找不到的(correct me if I am wrong!)。


2. Extension ClassLoader


這個類加載器主要加載JDK的擴(kuò)展類 /jre/lib/ext,它的實現(xiàn)類是 sun.misc.Launcher$ExtClassLoader :


static class ExtClassLoader extends URLClassLoader {
private static volatile Launcher.ExtClassLoader instance;

public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
if (instance == null) {
Class var0 = Launcher.ExtClassLoader.class;
synchronized(Launcher.ExtClassLoader.class) {
if (instance == null) {
instance = createExtClassLoader();
}
}
}

return instance;
}

我們看下它的實現(xiàn),實際上它創(chuàng)建了一個單例模式,使用的是雙重檢查加鎖,小師妹可以考慮一下怎么使用延遲初始化占位類的方式來重新這個類。


3. System ClassLoader


這個加載器是加載定義在ClassLoader中的類。它的實現(xiàn)類是sun.misc.Launcher$AppClassLoader,這個類的實現(xiàn)很長,這里就不完整列出來了:


static class AppClassLoader extends URLClassLoader 

在JDK9之后,因為引入了JPMS模塊的概念,所以類加載器變得不一樣了,在JDK9之后還是有三個內(nèi)置的類加載器,分別是BootClassLoader,PlatformClassLoader和AppClassLoader:

    private static class BootClassLoader extends BuiltinClassLoader {
BootClassLoader(URLClassPath bcp) {
super(null, null, bcp);
}

@Override
protected Class<?> loadClassOrNull(String cn, boolean resolve) {
return JLA.findBootstrapClassOrNull(this, cn);
}
};
private static class PlatformClassLoader extends BuiltinClassLoader 
private static class AppClassLoader extends BuiltinClassLoader

Linking階段主要做了三件事情:


  1. Verification – 主要驗證字節(jié)碼文件的結(jié)構(gòu)的正確性,如果不正確則會報LinkageError。

  2. Preparation – 負(fù)責(zé)創(chuàng)建static fields,并且初始化他們的值。

  3. Resolution – 把類型的常量池中引用的類,接口,字段和方法替換為直接引用的過程。


Initialization階段主要是調(diào)用class的父類和自身的初始化方法,來設(shè)置變量的初始值。

02

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


類加載好了,也初始化了,接下來就可以準(zhǔn)備運行了。


運行的時候要為數(shù)據(jù)分配運行空間,這就是運行時數(shù)據(jù)區(qū)域的作用。


運行時數(shù)據(jù)區(qū)域又可以分為5個部分:

1. Method Area


方法區(qū)是非Heap的內(nèi)存空間,主要用來存放class結(jié)構(gòu),static fields, method, method’s data 和 static fields等。


方法區(qū)是在JVM啟動的時候創(chuàng)建的,并且在所有的線程中共享。

JVM的架構(gòu)和執(zhí)行過程

Run-Time Constant Pool運行時常量池是放在方法區(qū)中的,他是class文件中constant_pool的運行時表現(xiàn)。


注意在JDK8之前,HotSpot JVM中對方法區(qū)的實現(xiàn)叫做持久代Perm Gen。


不過在JDK8之后,Perm Gen已經(jīng)被取消了,現(xiàn)在叫做Metaspace。Metaspace并不在java虛擬機(jī)中,它使用的是本地內(nèi)存。


Metaspace可以通過-XX:MaxMetaspaceSize來控制。

JVM的架構(gòu)和執(zhí)行過程

2. Heap Area


Heap Area主要存儲類對象和數(shù)組。垃圾回收器(GC)主要就是用來回收Heap Area中的對象的。

3. Stack Area


因為是棧的結(jié)構(gòu),所以這個區(qū)域總是LIFO(Last in first out)。我們考慮一個方法的執(zhí)行,當(dāng)方法執(zhí)行的時候,就會在Stack Area中創(chuàng)建一個block,這個block中持有對本地對象和其他對象的引用。一旦方法執(zhí)行完畢,則這個block就會出棧,供其他方法訪問。

4. PC Registers


PC Registers主要用來對程序的執(zhí)行狀態(tài)進(jìn)行跟蹤,比如保存當(dāng)前的執(zhí)行地址,和下一步的地址等。

5. Native Methods


最后一個就是本地方法區(qū)了,因為JVM的底層很多都是由C/C++來實現(xiàn)的,這些方法的實現(xiàn)就構(gòu)成了本地方法區(qū)。

03

執(zhí)行引擎


執(zhí)行引擎主要負(fù)責(zé)將java的字節(jié)碼翻譯成機(jī)器碼然后執(zhí)行。


先看一個java字節(jié)碼的內(nèi)在結(jié)構(gòu),大家可以隨便找一個編譯好的類,使用javap來進(jìn)行解析:

javap -v BufferUsage

JVM的架構(gòu)和執(zhí)行過程


這里不過多介紹輸出結(jié)果的含義,我們會在后面的文章中進(jìn)行詳解。


這我們可以看到方法中都有一個Code片段,這些Code被稱為OpCode,是JVM可以理解的操作命令。


執(zhí)行引擎中里面又有三個部分:

1. Interpreter


翻譯器用來讀取上面介紹的OpCode,并將其翻譯成為機(jī)器語言。因為翻譯器需要一個命令一個命令的翻譯字節(jié)碼,所以速度會比較慢。這就是很久很久以前Java被詬病的地方。

2. JIT (Just-In-Time) compiler


為了解決Interpreter翻譯慢的問題,JDK引入了JIT,對于那些經(jīng)常使用的代碼,JIT會將這些字節(jié)碼翻譯成為機(jī)器代碼,并直接復(fù)用這些機(jī)器代碼,從而提高了執(zhí)行效率。

3. Garbage Collector


GC用來回收Heap Area,他是一個Daemon thread。



總結(jié)


本文介紹了JVM的總體架構(gòu)信息。各個部分的細(xì)節(jié)信息會在后面的系列文章中陸續(xù)講解。歡迎大家關(guān)注小師妹系列。

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

JVM的架構(gòu)和執(zhí)行過程

長按訂閱更多精彩▼

JVM的架構(gòu)和執(zhí)行過程

如有收獲,點個在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉