自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JVM的執(zhí)行程序詳解+內(nèi)存模型交互

開發(fā) 開發(fā)工具
jvm它是一個(gè)虛構(gòu)出來的機(jī)器,但是它卻又是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種功能來實(shí)現(xiàn)的。

什么是JVM

jvm它是一個(gè)虛構(gòu)出來的機(jī)器,但是它卻又是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種功能來實(shí)現(xiàn)的。jvm包含了一套字節(jié)碼的指令集,有一組寄存器,一個(gè)棧,一個(gè)垃圾回收堆,一個(gè)存儲方法域。JVM使得Java程序只需要生成在Java虛擬機(jī)上運(yùn)行代碼,就可以在多種平臺不加什么修改地運(yùn)行。JVM在執(zhí)行字節(jié)碼的時(shí)候,最終還是把字節(jié)碼解釋成機(jī)器指令執(zhí)行。

JDK、JRE、JVM有什么關(guān)系

「JDK:」 也就是開發(fā)者用來編譯,調(diào)試程序用的開發(fā)包,JDK也需要JAVA程序,需要在JRE上運(yùn)行。

「JRE:」 Java平臺,所有的Java程序都要在JRE的環(huán)境才可以運(yùn)行。

「JVM:」 它是JRE的一部分,是一個(gè)虛構(gòu)出來的計(jì)算器,是通過在實(shí)際的計(jì)算機(jī)來模擬計(jì)算機(jī)功能實(shí)現(xiàn)的。

JVM執(zhí)行程序的過程

一個(gè)Java文件從編碼開始到執(zhí)行需要經(jīng)過幾個(gè)階段:

1、編譯階段:首先.java文件經(jīng)過了Javac進(jìn)行編譯成了.class文件。

2、加載階段:緊接著.class文件經(jīng)過了類加載器加載到JVM的內(nèi)存當(dāng)中。

3、解釋階段:class字節(jié)碼經(jīng)過了字節(jié)碼解釋器解析成系統(tǒng)可以識別到的指令碼

4、執(zhí)行階段:向硬件設(shè)備發(fā)送指令碼來進(jìn)行操作。

「再細(xì)講一下每一個(gè)階段」

編譯階段

****類的編譯階段主要的目的就是把源碼文件編譯成為可以讓JVM解析的class文件,這個(gè)階段會經(jīng)過的詞法分析、語法的語義分析。

class文件包含了哪些內(nèi)容呢?

「Magic Number:」 這個(gè)是在.class文件頭的四個(gè)字節(jié),作用的話就是定義識別的標(biāo)準(zhǔn),只有符合了標(biāo)準(zhǔn)才可以被JVM解讀。

「版本號:」 編譯class文件的JDK版本號,這些版本是可以向下兼容的

「常量池:」 常量池里的信息主要有字面量、基本類型常量、和符號引用(類和接口全限定名,方法名和描述符等等)。

「訪問標(biāo)志:」 該類是不是接口、注釋、枚舉、模塊。

「類索引:」 類的索引、父類的索引、接口的索引集合,用于來確定類的繼承實(shí)現(xiàn)關(guān)系。

「字段表集合:」 這個(gè)是用于描述接口或者是類里聲明變量的信息,如(public/private/protected)。

「方法表集合:」 方法表集合跟字段表集合類似,也就是用來保存方法的相關(guān)信息,包括了方法的名稱

「屬性表集合:」 這里包括了類、方法、實(shí)例變量的指令碼。

加載階段

加載這個(gè)階段就是主要把.class文件加載到JVM內(nèi)存里,這個(gè)階段有裝載、連接、初始化這三個(gè)流程

「裝載:」 裝載階段呢就是把class里的信息讀取到內(nèi)存當(dāng)中去,首先是通過了類的全限名讀取到此類的二進(jìn)制流,緊接著把字節(jié)流里描述靜態(tài)結(jié)構(gòu)的信息轉(zhuǎn)化成為方法區(qū)里的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。在加載階段的最后會在Java堆生成一個(gè)可以代表這個(gè)類的java.lang.class對象,作為了這個(gè)對象的訪問入口。

「連接:」 這個(gè)連接階段會進(jìn)行對class的信息來進(jìn)行驗(yàn)證,然后為類變量來分配內(nèi)存空間,并且賦予默認(rèn)值。首先是對class的內(nèi)容來驗(yàn)證字節(jié)是否符合了JVM的規(guī)范,然后為靜態(tài)的變量來分配內(nèi)存空間,最后進(jìn)行解析,把符號引用轉(zhuǎn)換成為直接引用,因?yàn)檫@里的類信息已經(jīng)在內(nèi)存當(dāng)中了,所以會把引用對象換成了對象在內(nèi)存里的實(shí)際地址。

「初始化:」 初始化階段主要是來執(zhí)行了初始化靜態(tài)塊的內(nèi)容,并且為靜態(tài)變量進(jìn)行真正的賦值。

解釋階段

解釋這個(gè)階段是在代碼執(zhí)行的期間觸發(fā)的,當(dāng)開始執(zhí)行一個(gè)類的方法的時(shí)候,首先是通過這個(gè)類的對象來作為入口,來找到相對應(yīng)的字節(jié)碼信息,然后再通過解釋器把字節(jié)碼解釋成指令碼。在最開始的執(zhí)行過程圖里有兩個(gè)解析器,解釋器有字節(jié)解釋器與即使編譯器JIT,一般的情況是運(yùn)行代碼的時(shí)候會使用的默認(rèn)字節(jié)碼解釋器來解析指令,只有是當(dāng)某一個(gè)方法是熱點(diǎn)方法,即使編譯器就會把熱點(diǎn)方法的指令碼進(jìn)行保存,等下次執(zhí)行的時(shí)候就不用重復(fù)的解析了,得以優(yōu)化。

執(zhí)行階段

操作系統(tǒng)把解釋器出來的指令碼,通過調(diào)用系統(tǒng)的硬件執(zhí)行最終的程序指令。

Java內(nèi)存間的交互操作

在Java的主內(nèi)存與工作內(nèi)存之間是如何來進(jìn)行具體的交互協(xié)議的呢?就是一個(gè)變量是怎么從主內(nèi)存拷貝到工作內(nèi)存的呢這一類細(xì)節(jié),在Java內(nèi)存模型中有八種操作,每一種操作都是原子的,不可再分的。

1、「lock(鎖定):」 鎖定這種操作作用于主內(nèi)存的變量,它會把一個(gè)變量標(biāo)記成為一條線程獨(dú)占的狀態(tài)

2、「unlock(解鎖):」 作用于主內(nèi)存的變量,把一個(gè)處于鎖定的變量釋放出來,釋放后的變量才可以被其他線程鎖定。

3、「read(讀取):」 作用于主內(nèi)存的變量,把一個(gè)變量從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存當(dāng)中,以便隨后的load使用。

4、「load(載入):」 作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入到工作內(nèi)存的變量副本當(dāng)中。

5、「use(使用):」 作用于工作內(nèi)存的變量,把工作內(nèi)存當(dāng)中的一個(gè)變量值傳遞給了執(zhí)行引擎

6、「assign(賦值):」 作用于工作內(nèi)存的變量,它把一個(gè)執(zhí)行引擎接受到的值賦給工作內(nèi)存的變量

7、「store(存儲):」 作用于工作內(nèi)存的變量,把工作內(nèi)存當(dāng)中的一個(gè)變量值傳送到主內(nèi)存當(dāng)中,以便隨后的write操作。

8、「write(寫入):」 作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中的一個(gè)變量的值傳送到主內(nèi)存的變量當(dāng)中。

上面的八種內(nèi)存交互操作必須滿足的規(guī)則

「第一、」 不允許read和load、store和write操作之一單獨(dú)出現(xiàn),即不允許一個(gè)變量從主內(nèi)存讀取了,但是工作內(nèi)存不接受,或者是從工作內(nèi)存發(fā)起了回寫了,但是主內(nèi)存不接受的情況出現(xiàn)。

「第二、」 不允許一個(gè)線程丟棄它的最近的assign操作,即變量在工作內(nèi)存當(dāng)中改變了之后就必須把該變化同步回主內(nèi)存。

「第三、」 不允許一個(gè)線程無原因地(沒有發(fā)生任何assign操作)把數(shù)據(jù)從線程的工作內(nèi)存同步回主內(nèi)存。

「第四、」 一個(gè)新的變量只能夠在主內(nèi)存“誕生”,不允許在工作內(nèi)存中直接使用一個(gè)未被初始化(load或assign)變量,換一句話來說就是對一個(gè)變量實(shí)施use、store操作之前,必須先執(zhí)行過了assign和load操作。

「第五、」 一個(gè)變量再次同一個(gè)時(shí)刻只允許一條線程對其進(jìn)行l(wèi)ock操作,但是lock操作可以被同一條線程重復(fù)執(zhí)行多次,多次執(zhí)行l(wèi)ock后,只有執(zhí)行相同次數(shù)的unlock操作,變量才回被解鎖。

「第六、」 如果對一個(gè)變量執(zhí)行l(wèi)ock操作,那將會清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個(gè)變量前,需要重新執(zhí)行l(wèi)oad或是assign操作初始化變量的值。

「第七、」 如果一個(gè)變量事先沒有被lock操作鎖定,那就不允許對它執(zhí)行unlock操作,也不允許去unlock一個(gè)被其他線程鎖定住的變量。

「第八、」 對一個(gè)變量執(zhí)行unlock操作之前,必須先把此變量同步回主內(nèi)存中(執(zhí)行store、write操作)。

Volatile變量的特殊規(guī)則

當(dāng)變量被定義成volatile之后,保證此變量對所有線程的可見性,這里所說的可見性是指當(dāng)一條線程修改了這個(gè) 變量的值,新值的話對于其他的線程來說是可以馬上得知的,普通的變量不可以做到這一點(diǎn),因?yàn)槠胀ㄗ兞康闹翟诰€程里的傳遞時(shí)均需要通過主內(nèi)存來完成。

Java內(nèi)存模型里對volatile變量定義的特殊規(guī)則有:

(1)線程對變量的load、read的操作需要連續(xù)的并且一起出現(xiàn)的,要求是在工作內(nèi)存當(dāng)中,每次使用變量的時(shí)候都必須要先從主內(nèi)存刷新最新的值,這也保證能看見其他線程對變量所做的修改。

(2)線程對變量store、write操作需要連續(xù)的并且是一起出現(xiàn)的,要求是在工作內(nèi)存當(dāng)中,每一次修改變量后都必須立刻的同步回主內(nèi)存當(dāng)中,用于保證其他線程可以看到自己對變量V所做的更改。


責(zé)任編輯:武曉燕 來源: 零零后程序員小三
相關(guān)推薦

2010-09-25 12:38:40

JVM內(nèi)存模型

2018-11-01 10:34:37

JVM內(nèi)存配置

2010-09-27 13:48:41

JVM內(nèi)存結(jié)構(gòu)

2010-12-10 15:40:58

JVM內(nèi)存管理

2019-05-06 08:37:14

JVMLinux內(nèi)存

2020-02-26 09:42:15

主存程序存儲器

2023-11-05 12:05:35

JVM內(nèi)存

2010-09-26 13:23:13

JVM內(nèi)存管理機(jī)制

2009-06-24 16:50:11

Java內(nèi)存模型

2018-07-04 14:43:55

對象模型內(nèi)存結(jié)構(gòu)內(nèi)存模型

2019-04-16 06:50:34

2019-08-30 07:24:16

2023-06-07 08:08:43

JVM內(nèi)存模型

2025-03-04 10:45:19

JVM內(nèi)存模型Java

2020-02-06 10:10:24

python程序代碼

2011-11-17 10:34:44

并行程序

2010-03-23 10:29:28

Python程序編譯轉(zhuǎn)

2010-02-22 08:58:35

JVM內(nèi)存模型垃圾收集

2009-06-04 16:27:39

Java虛擬機(jī)JVMGC

2024-07-26 10:23:52

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號