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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

java能够运行的原理_JAVA程序运行原理分析(一)

發(fā)布時(shí)間:2024/4/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java能够运行的原理_JAVA程序运行原理分析(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作為JAVA的開(kāi)發(fā)人員,需要知道JAVA是如何運(yùn)行的,這個(gè)需要好好思考下。

(一)class文件內(nèi)容

class文件包含JAVA程序執(zhí)行的字節(jié)碼,也就是說(shuō)程序的執(zhí)行是通過(guò)class里面的內(nèi)容進(jìn)行執(zhí)行的。class文件內(nèi)的信息嚴(yán)格按照一定的格式(虛擬機(jī)規(guī)范中的格式),緊湊排列在class文件中的二進(jìn)制流,中間無(wú)任何分隔符。

① 分析class文件內(nèi)的內(nèi)容

文件開(kāi)頭有一個(gè)0xcafebabe 16進(jìn)制的特殊的標(biāo)志,cafebabe就是java的class的標(biāo)識(shí)。

整個(gè)class文件很多很多的內(nèi)容,用肉眼肯定是無(wú)法分辨的,

② class包含的內(nèi)容

這個(gè)文件是有復(fù)雜格式,專門(mén)有JVM讀里面的內(nèi)容,方便閱讀源碼。

1.版本

源代碼是由java的哪個(gè)版本的編譯的。

2.訪問(wèn)標(biāo)志

這個(gè)類是public 還是private 。

3.常量池

常量哪些。

4.當(dāng)前類

當(dāng)前類的名稱,類的信息。

5.超級(jí)類

被繼承的類,類信息。

6.接口

實(shí)現(xiàn)的接口是什么?

7.字段

8.方法

9.屬性

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

java 源代碼編譯后生成 class字節(jié)碼,然后被加載到JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)里面

① 方法區(qū)

存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。虛擬機(jī)規(guī)范中的一個(gè)邏輯區(qū)域(沒(méi)有硬性的規(guī)定)。具體實(shí)現(xiàn)是根據(jù)不同的虛擬機(jī)來(lái)實(shí)現(xiàn)的。

如 oracle的Hotspot在java7中方法區(qū)放入永久代,java8放在元數(shù)據(jù)空間,并且通過(guò)GC機(jī)制對(duì)這個(gè)區(qū)域進(jìn)行管理。

② 堆

對(duì)象,垃圾回收,都是在堆中。

堆內(nèi)存還可以細(xì)分為:老年代,新生代(Eden,From Survivor,To Survivor)

JVM啟動(dòng)時(shí)就創(chuàng)建了,存放對(duì)象的實(shí)例,垃圾回收期主要就是管理堆內(nèi)存,內(nèi)存滿了,就會(huì)出現(xiàn)OutOfMemroyEorror,后續(xù)在內(nèi)存模型中,詳細(xì)講解。

③ 虛擬機(jī)棧

Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。一個(gè)方法對(duì)應(yīng)一個(gè)棧幀。棧內(nèi)存默認(rèn)最大是1M,超出則拋出StackOverflowError。計(jì)算,保存一些信息都是在棧里面。

④ 本地方法棧

和java虛擬機(jī)棧類似,不同的是其為Native方法服務(wù)。它跟java虛擬機(jī)棧的區(qū)別就是執(zhí)行的方法不同。

⑤ 程序計(jì)數(shù)器

當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器,每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器。每個(gè)線程都在這個(gè)控件有一個(gè)私有的空間,占用內(nèi)存空間很少。CPU同一時(shí)間,只會(huì)執(zhí)行一個(gè)線程中的指令。JVM多線程會(huì)輪流切換并分配CPU執(zhí)行時(shí)間的方式。為了線程切換后,需要通過(guò)程序計(jì)數(shù)器,來(lái)回復(fù)正確的執(zhí)行位置。

學(xué)習(xí)java,學(xué)習(xí)jvm,了解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū),這些就夠了,下面【執(zhí)行引擎】,【本地庫(kù)接口】,【本地方法庫(kù)】都是根據(jù)不同的操作系統(tǒng),不同的平臺(tái),做了JVM的適配,例如:linux,windows的執(zhí)行引擎,本地庫(kù)接口都有一些的不同,JVM的目的就是一處編寫(xiě)導(dǎo)出的運(yùn)行,作為開(kāi)發(fā)人員掌握在執(zhí)行引擎之上。

⑥ 線程獨(dú)占

每個(gè)線程都會(huì)有它獨(dú)立的空間,隨著生命周期而創(chuàng)建和消亡。【虛擬機(jī)棧,本地方法棧,程序計(jì)數(shù)器。】。

⑦ 線程共享

所有線程能訪問(wèn)這塊內(nèi)存數(shù)據(jù),隨著虛擬機(jī)或者GC而創(chuàng)建和消亡。【方法區(qū),堆】。

對(duì)象就是放入了堆中,也就是線程共享的。

(三)查看class文件內(nèi)容

① 找個(gè)例子

public class Demo1{

public static void main(String[] args){

int x = 600;

int y = 100;

int a = x / y;

int b = 60;

System.out.println(a + b);

}

}

②執(zhí)行下面的命令

使用Demo1.java進(jìn)行測(cè)試,編譯成class,完整的javap命令的解析結(jié)果

javac Demo1.java

// javap查看內(nèi)容,說(shuō)出Demo1.class所有的信息, 【>】意思是輸入到一個(gè)Demo1.txt文件

javap -v Demo1.class > Demo1.txt

java -version

③ 版本號(hào)、訪問(wèn)控制

flags: ACC PUBLIC,ACC SUPER

④ 常量池

這個(gè)常量池指的類里面包含的靜態(tài)常量,編譯這個(gè)類需要用到的常量,類的名稱類信息里面也是個(gè)常量,類本身需要用到的常量。

⑤ 構(gòu)造方法

之前類并沒(méi)有定義對(duì)應(yīng)的構(gòu)造方法,但是通過(guò)javap之后內(nèi)部存在一個(gè)無(wú)參的構(gòu)造方法。由此可見(jiàn),沒(méi)有定義構(gòu)造函數(shù)時(shí),會(huì)有隱式的無(wú)參構(gòu)造函數(shù)。

⑥ 程序入口main方法

描述了方法的:訪問(wèn)控制,本地變量的數(shù)目,參數(shù)的數(shù)量,方法對(duì)應(yīng)棧幀中操作的數(shù)棧的深度,JVM執(zhí)行引擎去執(zhí)行這些代碼編譯過(guò)后的指令碼,javap翻譯出來(lái)的操作符,class文件內(nèi)存儲(chǔ)的是指令碼,前面的數(shù)字,是偏移量,jvm根據(jù)這個(gè)去區(qū)分不同的指令。工具叫【JVM指令碼表】進(jìn)行查閱查看具體指令的含義。

(三)程序完整運(yùn)行分析

① 編譯加載到方法區(qū)

編譯加載到方法區(qū),最后加載Demo1,其實(shí)一個(gè)JVM運(yùn)行不止是一個(gè)Demo1,涉及到很多很多的類,會(huì)將所有的類信息存放到方法區(qū)里面,運(yùn)行的一些常量會(huì)放在常量池里面,1.7和之前稱為永久代,1.8開(kāi)始稱為元數(shù)據(jù)空間。

② 類加載進(jìn)去,創(chuàng)建對(duì)象運(yùn)行

類已經(jīng)加載進(jìn)去了,需要?jiǎng)?chuàng)建一個(gè)對(duì)象來(lái)進(jìn)行運(yùn)行,運(yùn)行代碼JVM創(chuàng)建線程來(lái)執(zhí)行這些代碼,一定是創(chuàng)建線程,需要配合【虛擬機(jī)棧】和【程序計(jì)數(shù)器】分配響應(yīng)的空間,這里不涉及到本地代碼因?yàn)樵蹅兌际窃贘VM里面,Thread有一個(gè)獨(dú)占的空間,其他區(qū)域有其他線程占領(lǐng),【程序計(jì)數(shù)器】對(duì)應(yīng)了字節(jié)碼指令的地址。

③ main方法

線程獨(dú)占空間,【程序計(jì)數(shù)器】標(biāo)注當(dāng)前這個(gè)線程執(zhí)行到得位置記錄下來(lái)有對(duì)應(yīng)的序號(hào),虛擬機(jī)棧里面開(kāi)辟了一個(gè)空間,一個(gè)棧有多個(gè)棧幀組成,方法對(duì)應(yīng)的一些操作,線程就是取一個(gè)或者多個(gè),其實(shí)線程就是對(duì)應(yīng)了一個(gè)或者多個(gè)棧幀,main方法的入口,也就是程序的入口,main方法棧幀包含本地變量表,操作數(shù)棧,Demo1 里面一共有5個(gè)變量,老鐵可能問(wèn)不是4個(gè)嗎,哪里來(lái)了5個(gè),因?yàn)閙ain方法里面的String[] args也是一個(gè)啊。

解析方法,看不懂對(duì)照【JVM指令碼表】

0: sipush 600 #將600這個(gè)數(shù)值壓入到操作數(shù)棧,棧從下往上

3: istore_1 #將操作棧頂保存到本地變量表1,移除操作棧

4: bipush 100 #將 600這個(gè)數(shù)值保存后,將100放入操作數(shù)棧

6: istore_2 #操作數(shù)棧棧頂100 保存到本地變量表2上。

7: iload_1 # 讀取本地變量1,壓入操作數(shù)棧1

8: iload_2 # 讀取本地變量2,壓入操作數(shù)棧,它變成位置1了,前一個(gè)操作數(shù)棧位置變成2了

9: idiv # 將棧頂兩int類型數(shù)相除,結(jié)果入棧600/100 = 6,原來(lái)操作數(shù)棧里面的100,600都移除。

10: istore_3 # 操作數(shù)棧棧頂6,保存到本地變量表3上。

11: bipush 60 #將 60這個(gè)數(shù)值保存后,將60放入操作數(shù)棧。

13: istore 4 # 將60放入操作數(shù)棧,放入本地變量表4的位置上。

15: getstatic #2 # 取貨類或者接口字段的值并將其推入操作數(shù)棧,#2對(duì)應(yīng)常量中,#2放入棧頂。

18: iload_3 #將本地變量3去取出壓入操作數(shù)棧

19: iload 4 # 將本地變量4取出來(lái)壓入操作數(shù)棧

21: iadd # 將棧頂兩個(gè)int類型數(shù)相加,結(jié)果入棧。

22: invokevirtual #3 // Method java/io/PrintStream.println:(I)V

# 調(diào)用靜態(tài)方法,新的一個(gè)方法,那個(gè)main方法不跑了,jvm會(huì)根據(jù)這個(gè)方法的描述,創(chuàng)建新棧幀,方法和操作從操作數(shù)棧中彈出來(lái),壓入虛擬機(jī)棧,然后虛擬機(jī)會(huì)開(kāi)始執(zhí)行虛擬機(jī)棧最上邊的棧幀,執(zhí)行完畢后,再繼續(xù)執(zhí)行main方法對(duì)應(yīng)的棧幀。

25: return # void函數(shù)返回,main方法執(zhí)行結(jié)果。

其實(shí)java的操作就是對(duì)于本地變量表,操作數(shù)棧,線程表里面的信息,操作,實(shí)現(xiàn)程序想要的效果,一定會(huì)要對(duì)照【JVM指令碼表】來(lái)看一定點(diǎn)分析幾個(gè),java的套路你就了解了。

PS:本次將JVM運(yùn)行的核心邏輯進(jìn)行了詳細(xì)的解析,JVM運(yùn)行原理中更底層實(shí)現(xiàn),針對(duì)不同的操作系統(tǒng)或者處理器,會(huì)有不同的實(shí)現(xiàn),說(shuō)了運(yùn)行時(shí)數(shù)據(jù)區(qū),講到了棧,指令碼的執(zhí)行過(guò)程。這也是JAVA能夠?qū)崿F(xiàn)【一定編寫(xiě),處處運(yùn)行】的原因。下次說(shuō)下Java線程。

總結(jié)

以上是生活随笔為你收集整理的java能够运行的原理_JAVA程序运行原理分析(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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