日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java虚拟机堆栈工作原理_java虚拟机工作原理?

發(fā)布時(shí)間:2025/3/12 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java虚拟机堆栈工作原理_java虚拟机工作原理? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

展開全部

從宏觀上介紹一下Java虛擬機(jī)的e5a48de588b662616964757a686964616f31333363373731工作原理。從最初編寫的Java源文件(.java文件)是如何一步步執(zhí)行的,如下圖所示,首先Java源文件經(jīng)過前端編譯器(javac或ECJ)將.java文件編譯為Java字節(jié)碼文件,然后JRE加載Java字節(jié)碼文件,載入系統(tǒng)分配給JVM的內(nèi)存區(qū),然后執(zhí)行引擎解釋或編譯類文件,再由即時(shí)編譯器將字節(jié)碼轉(zhuǎn)化為機(jī)器碼。主要介紹下圖中的類加載器和運(yùn)行時(shí)數(shù)據(jù)區(qū)兩個部分。

(1)類加載指將類的字節(jié)碼文件(.class)中的二進(jìn)制數(shù)據(jù)讀入內(nèi)存,將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆上創(chuàng)建java.lang.Class對象,封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。類加載的最終產(chǎn)品是位于堆中的類對象,類對象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向JAVA程序提供了訪問方法區(qū)內(nèi)數(shù)據(jù)結(jié)構(gòu)的接口。如下是類加載器的層次關(guān)系圖。

啟動類加載器(BootstrapClassLoader):在JVM運(yùn)行時(shí)被創(chuàng)建,負(fù)責(zé)加載存放在JDK安裝目錄下的jre\lib的類文件,或者被-Xbootclasspath參數(shù)指定的路徑中,并且能被虛擬機(jī)識別的類庫(如rt.jar,所有的java.*開頭的類均被Bootstrap ClassLoader加載)。啟動類無法被JAVA程序直接引用。

擴(kuò)展類加載器(Extension ClassLoader):該類加載器負(fù)責(zé)加載JDK安裝目錄下的\jre\lib\ext的類,或者由java.ext.dirs系統(tǒng)變量指定路徑中的所有類庫,開發(fā)者也可以直接使用擴(kuò)展類加載器。

應(yīng)用程序類加載器(AppClassLoader):負(fù)責(zé)加載用戶類路徑(Classpath)所指定的類,開發(fā)者可以直接使用該類加載器,如果應(yīng)用程序中沒有定義過自己的類加載器,該類加載器為默認(rèn)的類加載器。

用戶自定義類加載器(User ClassLoader):JVM自帶的類加載器是從本地文件系統(tǒng)加載標(biāo)準(zhǔn)的java class文件,而自定義的類加載器可以做到在執(zhí)行非置信代碼之前,自動驗(yàn)證數(shù)字簽名,動態(tài)地創(chuàng)建符合用戶特定需要的定制化構(gòu)建類,從特定的場所(數(shù)據(jù)庫、網(wǎng)絡(luò)中)取得java class。

注意如上的類加載器并不是通過繼承的方式實(shí)現(xiàn)的,而是通過組合的方式實(shí)現(xiàn)的。而JAVA虛擬機(jī)的加載模式是一種委派模式,如上圖中的1-7步所示。下層的加載器能夠看到上層加載器中的類,反之則不行。類加載器可以加載類但是不能卸載類。說了一大堆,還是感覺需要拿點(diǎn)代碼說事。

首先先定義自己的類加載器MyClassLoader,繼承自ClassLoader,并覆蓋了父類的findClass(String name)方法,如下:

利用定義的類加載器加載指定的字節(jié)碼文件,如通過MyClassLoader加載C:\\Users\\Administrator\\下的Test.class字節(jié)碼文件,代碼如下所示:

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

字節(jié)碼的加載第一步,其后分別是認(rèn)證、準(zhǔn)備、解析、初始化,那么這些步驟又具體做了哪些工作,如下圖所示:

(3)如下將介紹運(yùn)行時(shí)數(shù)據(jù)區(qū),主要分為方法區(qū)、Java堆、虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器。其中方法區(qū)和Java堆一樣,是各個線程共享的內(nèi)存區(qū)域,而虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器是線程私有的內(nèi)存區(qū)。

Java堆:Java堆是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊,被進(jìn)程的所有線程共享,在虛擬機(jī)啟動時(shí)被創(chuàng)建。該區(qū)域的唯一目的就是存放對象實(shí)例,幾乎所有的對象實(shí)例都在這里分配內(nèi)存,隨著JIT編譯器的發(fā)展與逃逸分支技術(shù)逐漸成熟,棧上分配、標(biāo)量替換等優(yōu)化技術(shù)使得對象在堆上的分配內(nèi)存變得不是那么“絕對”。Java堆是垃圾收集器管理的主要區(qū)域。由于現(xiàn)在的收集器基本都采用分代收集算法,所以Java堆中還可以分為老年代和新生代(Eden、From Survivor、To Survivor)。根據(jù)Java虛擬機(jī)規(guī)范,Java堆可以處于物理上不連續(xù)的內(nèi)存空間,只要邏輯上連續(xù)即可。該區(qū)域的大小可以通過-Xmx和-Xms參數(shù)來擴(kuò)展,如果堆中沒有內(nèi)存完成實(shí)例分配,并且堆也無法擴(kuò)展,將會拋出OutOfMemoryError異常。

方法區(qū):用于存儲被Java虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。不同于Java堆的是,Java虛擬機(jī)規(guī)范對方法區(qū)的限制非常寬松,可以選擇不實(shí)現(xiàn)垃圾收集。但并非數(shù)據(jù)進(jìn)入了方法區(qū)就“永久”存在了,這區(qū)域內(nèi)存回收目標(biāo)主要是針對常量池的回收和對類型的卸載。如果該區(qū)域內(nèi)存不足也會拋出OutOfMemoryError異常。

常量池:這個名詞可能大家也經(jīng)常見,是方法區(qū)的一部分。Class文件除了有類的版本、字段、方法、接口等描述信息外,還有一項(xiàng)信息就是常量池,用于存放編譯期生成的各種字面量和符號引用。Java虛擬機(jī)運(yùn)行期間,也可能將新的常量放入常量池(如String類的intern()方法)。

虛擬機(jī)棧:線程私有,生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行時(shí)都會創(chuàng)建一個棧幀用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。每個方法從調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機(jī)棧中入棧到出棧的過程。如果請求的站深度大于虛擬機(jī)所允許的深度,將拋出StackOverflowError異常,虛擬機(jī)棧在動態(tài)擴(kuò)展時(shí)如果無法申請到足夠的內(nèi)存,就會拋出OutOfMemoryError異常。

過最簡單的一段代碼解釋一下,程序在運(yùn)行時(shí)數(shù)據(jù)區(qū)個部分的變化情況。

(4)通過編譯器將Test.java文件編譯為Test.class,利用javap -verbose Test.class對編譯后的字節(jié)碼進(jìn)行分析,如下圖所示:

(5)看看運(yùn)行時(shí)數(shù)據(jù)區(qū)的變化:

總結(jié)

以上是生活随笔為你收集整理的java虚拟机堆栈工作原理_java虚拟机工作原理?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。