一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

java虛擬機(jī)體系分析

 汗血寶馬6 2016-07-30

一、JVM的生命周期:

1)程序開始執(zhí)行,他就運(yùn)行,程序停止,它就結(jié)束。有幾個(gè)程序在執(zhí)行,就有幾個(gè)虛擬機(jī)在工作。只要Java虛擬機(jī)中還有普通的線程在執(zhí)行,Java虛擬機(jī)就不會停止。

2)Java虛擬機(jī)總是開始于一個(gè)main方法,這個(gè)方法必須是公有、返回void、接受一個(gè)字符串?dāng)?shù)組。在程序執(zhí)行時(shí),你必須給Java虛擬機(jī)指明這個(gè)包含main方法的類名。 Main方法是程序的起點(diǎn),他被執(zhí)行的線程初始化為程序的初始線程。程序中其他的線程都由他來啟動(dòng)。

3)Java中的線程分為兩種:守護(hù)線程 (daemon)和普通線程(non-daemon)。守護(hù)線程是Java虛擬機(jī)自己使用的線程,比如負(fù)責(zé)垃圾收集的線程就是一個(gè)守護(hù)線程。包含Main方法的初始線程不是守護(hù)線程。

4)在Java虛擬機(jī)的規(guī)范中定義了一系列的子系統(tǒng)、內(nèi)存區(qū)域、數(shù)據(jù)類型和使用指南。這些組件構(gòu)成了Java虛擬機(jī)的內(nèi)部結(jié)構(gòu),他們不僅僅為Java虛擬機(jī)的實(shí)現(xiàn)提供了清晰的內(nèi)部結(jié)構(gòu),更是嚴(yán)格規(guī)定了Java虛擬機(jī)實(shí)現(xiàn)的外部行為。

java虛擬機(jī)體系分析

二、java虛擬機(jī)的體系結(jié)構(gòu):

每一個(gè)Java虛擬機(jī)都由一個(gè)類加載器子系統(tǒng)負(fù)責(zé)加載程序中的類型(類和接口),并賦予唯一的名字。每一個(gè)Java虛擬機(jī)都有一個(gè)執(zhí)行引擎(execution engine)負(fù)責(zé)執(zhí)行被加載類中包含的指令。

程序的執(zhí)行需要一定的內(nèi)存空間,如字節(jié)碼、被加載類的其他額外信息、程序中的對象、方法的參數(shù)、返回值、本地變量、處理的中間變量等等。Java虛擬機(jī)將這些信息統(tǒng)統(tǒng)保存在數(shù)據(jù)區(qū)中。

每個(gè)Java虛擬機(jī)的實(shí)現(xiàn)中都包含數(shù)據(jù)區(qū),但是Java虛擬機(jī)規(guī)范對數(shù)據(jù)區(qū)的規(guī)定卻非常的抽象。許多結(jié)構(gòu)上的細(xì)節(jié)部分都留給了 Java虛擬機(jī)實(shí)現(xiàn)者自己發(fā)揮。不同Java虛擬機(jī)實(shí)現(xiàn)上的內(nèi)存結(jié)構(gòu)千差萬別。一部分實(shí)現(xiàn)可能占用很多內(nèi)存,而其他以下可能只占用很少的內(nèi)存;一些實(shí)現(xiàn)可能會使用虛擬內(nèi)存,而其他的則不使用。這種比較精煉的Java虛擬機(jī)內(nèi)存規(guī)約,可以使得Java虛擬機(jī)可以在廣泛的平臺上被實(shí)現(xiàn)。

數(shù)據(jù)區(qū)中的一部分是整個(gè)程序共有,其他部分被單獨(dú)的線程控制。每一個(gè)Java虛擬機(jī)都包含方法區(qū)(method area)和堆(heap),他們都被整個(gè)程序共享。

Java虛擬機(jī)加載并解析一個(gè)類以后,將從類文件中解析出來的信息保存在方法區(qū)(保存解析出的類的信息)中。程序執(zhí)行時(shí)創(chuàng)建的對象都保存在堆(保存對象)中。

當(dāng)一個(gè)線程被創(chuàng)建時(shí),會被分配只屬于他自己的PC寄存器“pc register”(程序計(jì)數(shù)器)和Java堆棧(Java stack)。當(dāng)線程不掉用本地方法時(shí),其作用是,PC寄存器中保存線程執(zhí)行的下一條指令。Java堆棧保存了一個(gè)線程調(diào)用方法時(shí)的狀態(tài),包括本地變量、調(diào)用方法的 參數(shù)、返回值、處理的中間變量。調(diào)用本地方法時(shí)的狀態(tài)保存在本地方法堆棧中,可能在寄存器或者其他非平臺獨(dú)立的內(nèi)存中。

Java堆棧有堆棧塊組成。堆棧塊包含Java方法調(diào)用的狀態(tài)。當(dāng)一個(gè)線程調(diào)用一個(gè)方法時(shí),Java虛擬機(jī)會將一個(gè)新的塊壓到Java堆棧中,當(dāng)這個(gè)方法運(yùn)行結(jié)束時(shí),Java虛擬機(jī)會將對應(yīng)的塊彈出并拋棄。

區(qū)別:Java虛擬機(jī)不使用寄存器保存計(jì)算的中間結(jié)果,而是用Java堆棧在存放中間結(jié)果。這是的Java虛擬機(jī)的指令更緊湊,也更容易在一個(gè)沒有寄存器的設(shè)備上實(shí)現(xiàn)Java虛擬機(jī)。

三、類加載器子系統(tǒng):

Java虛擬機(jī)中的類加載器分為兩種:原始類加載器(primordial class loader)和類加載器對象(class loader objects)。特點(diǎn):原始類加載器是Java虛擬機(jī)實(shí)現(xiàn)的一部分,類加載器對象是運(yùn)行中的程序的一部分。不同類加載器加載的類被不同的命名空間所分割。

類加載器調(diào)用了許多Java虛擬機(jī)中其他的部分和java.lang包中的很多類。比如,類加載對象就是java.lang.ClassLoader子類的實(shí)例,ClassLoader類中的方法可以訪問虛擬機(jī)中的類加載機(jī)制。

每一個(gè)被Java虛擬機(jī)加載的類都會被表示為一個(gè)java.lang.Class類的實(shí)例。像其他對象一樣,類加載器對象和Class對象都保存在堆中,被加載的信息被保存在方法區(qū)中。

類加載器所做的工作:

1、加載、連接、初始化(Loading, Linking and Initialization)

類加載子系統(tǒng)不僅僅負(fù)責(zé)定位并加載類文件,他按照以下嚴(yán)格的步驟作了很多其他的事情:

1)、加載:尋找并導(dǎo)入指定類型(類和接口)的二進(jìn)制信息

2)、連接:進(jìn)行驗(yàn)證、準(zhǔn)備和解析

①驗(yàn)證:確保導(dǎo)入類型的正確性

②準(zhǔn)備:為類型分配內(nèi)存并初始化為默認(rèn)值

③解析:將字符引用解析為直接引用

3)、初始化:調(diào)用Java代碼,初始化類變量為合適的值

2、原始類加載器

每個(gè)Java虛擬機(jī)都必須實(shí)現(xiàn)一個(gè)原始類加載器,他能夠加載那些遵守類文件格式并且被信任的類。但是,Java虛擬機(jī)的規(guī)范并沒有定義如何加載類,這由 Java虛擬機(jī)實(shí)現(xiàn)者自己決定。對于給定類型名的類型,原始類加載器必須找到那個(gè)類型名加“.class”的文件并加載入虛擬機(jī)中。

3、類加載器對象

雖然類加載器對象是Java程序的一部分,但是ClassLoader類中的三個(gè)方法可以訪問Java虛擬機(jī)中的類加載子系統(tǒng)。

1)、protected final Class defineClass(…):使用這個(gè)方法可以輸入一個(gè)字節(jié)數(shù)組,定義一個(gè)新的類型。

2)、protected Class findSystemClass(String name):加載指定的類,如果已經(jīng)加載,就直接返回。

3)、protected final void resolveClass(Class c):defineClass方法只是加載一個(gè)類,這個(gè)方法負(fù)責(zé)后續(xù)的動(dòng)態(tài)連接和初始化。

4、命名空間

當(dāng)多個(gè)類加載器加載了同一個(gè)類時(shí),為了保證他們名字的唯一性,需要在類名前加上加載該類的類加載器的標(biāo)識。

java虛擬機(jī)體系分析

四、方法區(qū):

在Java虛擬機(jī)中,被加載類型的信息都保存在方法區(qū)中。這些信息在內(nèi)存中的組織形式由虛擬機(jī)的實(shí)現(xiàn)者定義,比如,虛擬機(jī)工作在一個(gè)“l(fā)ittle- endian”的處理器上,他就可以將信息保存為“l(fā)ittle-endian”格式的,雖然在Java類文件中他們是以“big-endian”格式保存的。設(shè)計(jì)者可以用最適合的表示格式來存儲數(shù)據(jù),以保證程序能夠以最快的速度執(zhí)行。但是,在一個(gè)只有很小內(nèi)存的設(shè)備上,虛擬機(jī)的實(shí)現(xiàn)者就不會占用很大的內(nèi)存。

程序中的所有線程共享一個(gè)方法區(qū),所以訪問方法區(qū)信息的方法必須是線程安全的。如果你有兩個(gè)線程都去加載一個(gè)叫Lava的類,那只能由一個(gè)線程被容許去加載這個(gè)類,另一個(gè)必須等待。

在程序運(yùn)行時(shí),方法區(qū)的大小是可變的,程序在運(yùn)行時(shí)可以擴(kuò)展。有些Java虛擬機(jī)的實(shí)現(xiàn)也可以通過參數(shù)設(shè)定方法區(qū)的初始大小,最小值和最大值。

方法區(qū)也可以被垃圾收集。因?yàn)槌绦蛑械挠深惣虞d器動(dòng)態(tài)加載,所有類可能變成沒有被引用(unreferenced)(雖然已經(jīng)加載進(jìn)來,但是沒有引用?。┑臓顟B(tài)。當(dāng)類變成這種狀態(tài)時(shí),他就可能被垃圾收集掉。沒有加載的類包括兩種狀態(tài),一種是真正的沒有加載,另一個(gè)種是“unreferenced”的狀態(tài)。

1、類型信息(Type Information)

每一個(gè)被加載的類型,在Java虛擬機(jī)中都會在方法區(qū)中保存如下信息:

1)、類型的全名

2)、類型的父類型的全名

3)、給類型是一個(gè)類還是接口

4)、類型的修飾符

5)、 所有父接口全名的列表

類型全名保存的數(shù)據(jù)結(jié)構(gòu)由虛擬機(jī)實(shí)現(xiàn)者定義。除此之外,Java虛擬機(jī)還要為每個(gè)類型保存如下信息:

1)、類型的常量池

2)、類型字段的信息

3)、類型方法的信息

4)、 所有的靜態(tài)類變量(非常量)信息

5)、一個(gè)指向類加載器的引用

6)、一個(gè)指向Class類的引用

7)、類型的常量池

常量池中保存中所有類型是用的有序的常量集合,包含直接常量(literals)如字符串、整數(shù)、浮點(diǎn)數(shù)的常量,和對類型、字段、方法的符號引用。常量池中每一個(gè)保存的常量都有一個(gè)索引,就像數(shù)組中的字段一樣。因?yàn)槌A砍刂斜4嬷兴蓄愋褪褂玫降念愋?、字段、方法的字符引用,所以它也是?dòng)態(tài)連接的主要對象。

2)、類型字段的信息(Field information)

字段名、字段類型、字段的修飾符、字段在類中定義的順序。

3)、類型方法的信息(Method information)

方法名、方法的返回值類型(或者是void)、方法參數(shù)的個(gè)數(shù)、類型和他們的順序、字段的修飾符、方法在類中定義的順序

4)、類(靜態(tài)static)變量

類變量被所有類的實(shí)例共享,即使不通過類的實(shí)例也可以訪問。這些變量綁定在類上(而不是類的實(shí)例上),所以他們是類的邏輯數(shù)據(jù)的一部分。在Java虛擬機(jī)使用這個(gè)類之前就需要為類變量分配內(nèi)存

常量(final)的處理方式于這種類變量不一樣。每一個(gè)類型在用到一個(gè)常量的時(shí)候,都會復(fù)制一份到自己的常量池中。常量也像類變量一樣保存在方法區(qū)中,只不過他保存在常量池中。(可能是,類變量被所有實(shí)例共享,而常量池是每個(gè)實(shí)例獨(dú)有的)。Non-final類變量保存為定義他的類型數(shù)據(jù)的一部分,而final常量保存為使用他的類型數(shù)據(jù)的一部分。

5)、指向類加載器的引用

每一個(gè)被Java虛擬機(jī)加載的類型,虛擬機(jī)必須保存這個(gè)類型是否由原始類加載器或者類加載器加載。那些被類加載器加載的類型必須保存一個(gè)指向類加載器的引用。當(dāng)類加載器動(dòng)態(tài)連接時(shí),會使用這條信息。當(dāng)一個(gè)類引用另一個(gè)類時(shí),虛擬機(jī)必須保存那個(gè)被引用的類型是被同一個(gè)類加載器加載的,這也是虛擬機(jī)維護(hù)不同命名空間的過程。

6)、指向Class類的引用(class.forName的作用)

Java虛擬機(jī)為每一個(gè)加載的類型創(chuàng)建一個(gè)java.lang.Class類的實(shí)例。你也可以通過Class類的方法:public static Class forName(String className)來查找或者加載一個(gè)類,并取得相應(yīng)的Class類的實(shí)例。

2、方法列表(Method Tables)

為了更有效的訪問所有保存在方法區(qū)中的數(shù)據(jù),這些數(shù)據(jù)的存儲結(jié)構(gòu)必須經(jīng)過仔細(xì)的設(shè)計(jì)。所有方法區(qū)中,除了保存了上邊的那些原始信息外,還有一個(gè)為了加快存取速度而設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu),比如方法列表。每一個(gè)被加載的非抽象類,Java虛擬機(jī)都會為他們產(chǎn)生一個(gè)方法列表,這個(gè)列表中保存了這個(gè)類可能調(diào)用的所有實(shí)例方法的引用,報(bào)錯(cuò)那些父類中調(diào)用的方法。

五、堆:

當(dāng)Java程序創(chuàng)建一個(gè)類的實(shí)例或者數(shù)組時(shí),都在堆中為新的對象分配內(nèi)存。虛擬機(jī)中只有一個(gè)堆,所有的線程都共享它(方法區(qū)也是可以被共享的?。?。

1、垃圾收集(Garbage Collection)

垃圾收集是釋放沒有被引用的對象的主要方法。它也可能會為了減少堆的碎片,而移動(dòng)對象。在Java虛擬機(jī)的規(guī)范中沒有嚴(yán)格定義垃圾收集,只是定義一個(gè)Java虛擬機(jī)的實(shí)現(xiàn)必須通過某種方式管理自己的堆。

2、對象存儲結(jié)構(gòu)(Object Representation)

Java虛擬機(jī)的規(guī)范中沒有定義對象怎樣在堆中存儲。每一個(gè)對象主要存儲的是他的類和父類中定義的對象變量。對于給定的對象的引用,虛擬機(jī)必須能很快的定位到這個(gè)對象的數(shù)據(jù)。另外,必須提供一種通過對象的引用方法對象數(shù)據(jù)的方法,比如方法區(qū)中的對象的引用,所以一個(gè)對象保存的數(shù)據(jù)中往往含有一個(gè)某種形式指向方法區(qū)的指針。

1)一個(gè)可能的堆的設(shè)計(jì)是將堆分為兩個(gè)部分:引用池和對象池。一個(gè)對象的引用就是指向引用池的本地指針。每一個(gè)引用池中的條目都包含兩個(gè)部分:指向?qū)ο蟪刂袑ο髷?shù)據(jù)的指針和方法區(qū)中對象類數(shù)據(jù)的指針。這種設(shè)計(jì)能夠方便Java虛擬機(jī)堆碎片的整理。當(dāng)虛擬機(jī)在對象池中移動(dòng)一個(gè)對象的時(shí)候,只需要修改對應(yīng)引用池中的指針地址。(理解:在引用池中一個(gè)引用就指向了一個(gè)對應(yīng)的對象,移動(dòng)對象的實(shí)質(zhì)就是修改引用池的地址?。┑敲看卧L問對象的數(shù)據(jù)都需要處理兩次指針。

2)另一種堆的設(shè)計(jì)是:一個(gè)對象的引用就是一個(gè)指向一堆數(shù)據(jù)和指向相應(yīng)對象的偏移指針。這種設(shè)計(jì)方便了對象的訪問,可是對象的移動(dòng)要變的異常復(fù)雜。

當(dāng)程序試圖將一個(gè)對象轉(zhuǎn)換為另一種類型時(shí),虛擬機(jī)需要判斷這種轉(zhuǎn)換是否是這個(gè)對象的類型,或者是他的父類型。當(dāng)程序適用instanceof語句的時(shí)候也會做類似的事情。當(dāng)程序調(diào)用一個(gè)對象的方法時(shí),虛擬機(jī)需要進(jìn)行動(dòng)態(tài)綁定,他必須判斷調(diào)用哪一個(gè)類型的方法。這也需要做上面的判斷。

無論虛擬機(jī)實(shí)現(xiàn)者使用哪一種設(shè)計(jì),他都可能為每一個(gè)對象保存一個(gè)類似方法列表的信息。因?yàn)樗梢蕴嵘龑ο蠓椒ㄕ{(diào)用的速度,對提升虛擬機(jī)的性能非常重要,但是虛擬機(jī)的規(guī)范中比沒有要求必須實(shí)現(xiàn)類似的數(shù)據(jù)結(jié)構(gòu)。

每一個(gè)Java虛擬機(jī)中的對象必須關(guān)聯(lián)一個(gè)用于同步多線程lock(mutex)。同一時(shí)刻,只能有一個(gè)對象擁有這個(gè)對象的鎖。當(dāng)一個(gè)擁有這個(gè)對象的鎖,他就可以多次申請這個(gè)鎖,但是也必須釋放相應(yīng)次數(shù)的鎖才能真正釋放這個(gè)對象鎖。很多對象在整個(gè)生命周期中都不會被鎖,所以這個(gè)信息只有在需要時(shí)才需要添加。很多Java虛擬機(jī)的實(shí)現(xiàn)都沒有在對象的數(shù)據(jù)中包含“鎖定數(shù)據(jù)”,只是在需要時(shí)才生成相應(yīng)的數(shù)據(jù)。除了實(shí)現(xiàn)對象的鎖定,每一個(gè)對象還邏輯關(guān)聯(lián)到一 個(gè)“wait set”的實(shí)現(xiàn)。鎖定幫組線程獨(dú)立處理共享的數(shù)據(jù),不需要妨礙其他的線程。“wait set”幫組線程協(xié)作完成同一個(gè)目標(biāo)?!皐ait set”往往通過Object類的wait和notify方法來實(shí)現(xiàn)。

垃圾收集也需要堆中的對象是否被關(guān)聯(lián)的信息。Java虛擬機(jī)規(guī)范中指出垃圾收集一個(gè)運(yùn)行一個(gè)對象的finalize方法一次,但是容許 finalize方法重新引用這個(gè)對象,當(dāng)這個(gè)對象再次不被引用時(shí),就不需要再次調(diào)用finalize方法。所以虛擬機(jī)也需要保存finalize方法 是否運(yùn)行過的信息。

3、數(shù)組的保存(Array Representation)

在Java 中,數(shù)組是一種完全意義上的對象,他和對象一樣保存在堆中、有一個(gè)指向Class類實(shí)例的引用。所有同一維度和類型的數(shù)組擁有同樣的Class,數(shù)組的長度不做考慮。對應(yīng)Class的名字表示為維度和類型數(shù)組必須在堆中保存數(shù)組的長度,數(shù)組的數(shù)據(jù)和一些對象數(shù)組類型數(shù)據(jù)的引用。通過一個(gè)數(shù)組引用的,虛擬機(jī)應(yīng)該能夠取得一個(gè)數(shù)組的長度,通過索引能夠訪問特定的數(shù)據(jù),能夠調(diào)用Object定義的方法。Object是所有數(shù)據(jù)類的直接父類。

java虛擬機(jī)體系分析

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产日韩中文视频一区| 激情丁香激情五月婷婷| 亚洲中文字幕乱码亚洲| 日韩免费av一区二区三区| 国产精品一区二区视频大全| 高潮日韩福利在线观看| 日本熟女中文字幕一区| 成人国产激情在线视频| 色婷婷日本视频在线观看| 欧美亚洲另类久久久精品| 亚洲一区二区精品免费视频| 亚洲最大福利在线观看| 美日韩一区二区精品系列| 日韩欧美一区二区黄色| 亚洲国产av在线观看一区| 国产情侣激情在线对白| 日韩蜜桃一区二区三区| 日韩人妻毛片中文字幕| 日韩少妇人妻中文字幕| 日韩中文字幕免费在线视频| 亚洲国产精品一区二区毛片| 中文字幕高清免费日韩视频| 亚洲一区二区欧美激情| 97人妻精品一区二区三区免| 人妻乱近亲奸中文字幕| 一区二区三区日韩中文| 黄色片一区二区在线观看| 国产传媒免费观看视频| 日韩免费av一区二区三区| 欧美特色特黄一级大黄片| 国产又色又爽又黄的精品视频| 中文字幕亚洲精品人妻| 欧美不雅视频午夜福利| 欧美日韩一区二区午夜| 欧美成人国产精品高清| 日韩专区欧美中文字幕| 在线免费观看一二区视频| 亚洲av成人一区二区三区在线| 国产又黄又猛又粗又爽的片| 亚洲一区二区精品福利| av免费视屏在线观看|