1,、Java虛擬機是什么 “Java虛擬機“可以指三種不同的東西 抽象規(guī)范 一個具體的實現(xiàn) 一個運行中的虛擬機實例 當(dāng)運行一個Java程序的同時,也就是在運行一個Java虛擬機實例 2,、Java虛擬機的生命周期 當(dāng)啟動一個Java程序時,,一個虛擬機實例也就誕生了,當(dāng)該程序關(guān)閉退出時,,這個虛擬機實例也就隨之消亡,。 在java虛擬機內(nèi)部有兩種線程:守護線程和非守護線程。當(dāng)該程序中所有的非守護線程都終止時,,虛擬機實例將自動退出,。 3、Java虛擬機的體系結(jié)構(gòu) 一個虛擬機實例的行為是分別按照子系統(tǒng),、內(nèi)存區(qū),、數(shù)據(jù)類型以及指令這幾個術(shù)語來描述的。 3.1,、數(shù)據(jù)類型 Java語言中所有的基本類型同樣也都是Java虛擬機中的基本類型,。但boolean有點特別,指令集對boolean只有很有限的支持,。當(dāng)編譯器把Java源碼編譯為字節(jié)碼的時,,它會用int或byte來表示boolean。Boolean數(shù)組是當(dāng)byte數(shù)組來訪問的,。 returnAddress是Java虛擬機內(nèi)部使用的基本類型,,這個類型被用來實現(xiàn)Java程序中的finally子句。 3.2,、類裝載器子系統(tǒng) 負(fù)責(zé)查找并裝載的那部分被稱為類裝載器子系統(tǒng),。 分為啟動類裝載器和用戶自定義類裝載器 由不同的類裝載器裝載的類將放在虛擬機內(nèi)部的不同命名空間中。 用戶自定義的類裝載器以及Class類的實例都放在內(nèi)存的堆區(qū),,而裝載的類型信息則都位于方法區(qū),。 裝載順序: 1)裝載——查找并裝載類型的二進制數(shù)據(jù) 2)連接——執(zhí)行驗證(確保被導(dǎo)入類型的正確性),準(zhǔn)備(為類變量分配內(nèi)存,,并將其初始化為默認(rèn)值),,以及解析(把類變量中的符號引用轉(zhuǎn)換為正確的初始值) 3)初始化——把類變量初始化為正確的初始值 3.3方法區(qū) 在java虛擬機中,關(guān)于被裝載類型的信息存儲在一個邏輯上被稱為方法區(qū)的內(nèi)存中,。 所有線程都共享方法區(qū),。 類型信息: 這個類型的全限定名 這個類型的直接超類的全限定名 這個類型是類類型還是接口類型 這個類型的訪問修飾符 任何直接超接口的全限定名的有序列表 該類型的常量池 字段信息 方法信息 除了常量以外的所有類(靜態(tài))變量 一個到類ClassLoader的引用 一個到Class類的引用 其中字段信息包括 字段名 字段類型 字段的修飾符 方法信息包括 方法名 方法的返回類型 方法參數(shù)的數(shù)量和類型 方法的修飾符 如果方法不是抽象的和本地的還須有 方法的字節(jié)碼 操作數(shù)棧和該方法的棧幀中的局部變量的大小 異常表 3.4 堆 Java程序在運行時所創(chuàng)建的所有類實例或數(shù)組都放在同一個堆中。 Java對象中包含的基本數(shù)據(jù)由它所屬的類及其所有超類聲明的實例變量組成,。只要有一個對象引用,,虛擬機就必須能快速的定位對象實例的數(shù)據(jù),,另外,它必須能通過該對象引用訪問相應(yīng)的類數(shù)據(jù),,因此對象中通常有一個指向方法區(qū)的指針,。 一種可能的堆空間設(shè)計就是,把堆分為兩部分:一個句柄池,,一個對象池,。 這種設(shè)計的好處是有利于堆碎片的整理,缺點是每次訪問對象的實例變量都需要經(jīng)過兩次指針傳遞,。 另一種設(shè)計方式是使對象直接指向一組數(shù)據(jù),而數(shù)據(jù)包括對象實例數(shù)據(jù)以及指向方法區(qū)類數(shù)據(jù)的指針,。這種設(shè)計方式的優(yōu)點是只需要一個指針就可以訪問對象的實例數(shù)據(jù),,但是移動對象就變得更加復(fù)雜。 堆中其他數(shù)據(jù): 1,、對象鎖,,用于協(xié)調(diào)多個線程訪問一個對象時的同步。 2,、等待集合 3,、與垃圾收集器有關(guān)的數(shù)據(jù)。 4,、方法表:加快了調(diào)用實例方法時的效率,。 方法表指向的實例方法數(shù)據(jù)包括以下信息: 此方法的操作數(shù)棧和局部變量區(qū)的大小 此方法的字節(jié)碼 異常表 這些信息足夠虛擬機去調(diào)用一個方法了,方法表包含有方法指針——指向類活或超類聲明的方法的數(shù)據(jù) 3.5程序計數(shù)器 對于一個運行中的Java程序而言,,其中的每一個線程都有它自己的PC(程序計數(shù)器),,在線程啟動時創(chuàng)建。大小是一個字長,。當(dāng)線程執(zhí)行某個Java方法時,,PC的內(nèi)容總是下一條將被指向指令的“地址”。如果該線程正在執(zhí)行一個本地方法,,那么此時PC的值為”undefined”,。Java棧 3.6Java棧 每當(dāng)啟動一個線程時,Java虛擬機都會為它分配一個Java棧,,Java棧也幀為單位保存線程的運行狀態(tài),,虛擬機只會直接對Java棧執(zhí)行兩種操作:以幀為單位的壓棧和出棧。 某個線程正在執(zhí)行的方法被稱為該線程的當(dāng)前方法,,當(dāng)前方法使用的棧幀稱為當(dāng)前幀,,當(dāng)前方法所屬的類稱為當(dāng)前類,當(dāng)前類的常量池稱為當(dāng)前常量池,,在線程執(zhí)行一個方法時,,它會跟蹤當(dāng)前類和當(dāng)前常量池,。 每當(dāng)線程調(diào)用一個方法時,虛擬機都會在該線程的Java棧中壓入一個新幀,,而這個新棧自然就成為當(dāng)前幀,。在執(zhí)行這個方法時,它使用這個幀來存儲參數(shù),、局部變量,、中間運算結(jié)果等等數(shù)據(jù)。 Java棧上的所有數(shù)據(jù)都是數(shù)據(jù)都是此線程私有的,。 3.7棧幀 棧幀由三部分組成:局部變量區(qū),、操作數(shù)棧和幀數(shù)據(jù)區(qū)。局部變量區(qū)和操作數(shù)棧的大小要視對應(yīng)的方法而定,,編譯器在編譯器時就確定的確定了這些值并放在class文件中,。幀數(shù)據(jù)區(qū)的大小依賴于具體的實現(xiàn)。 當(dāng)虛擬機調(diào)用一個方法時,,它從對應(yīng)類的類型信息中得到此方法的局部變量區(qū)和操作數(shù)棧的大小,,并據(jù)此分配棧幀內(nèi)存,然后壓入Java棧中,。 局部變量區(qū):Java棧幀的局部變量區(qū)被組織為以一個字長為單位,、從0開始計數(shù)的數(shù)組。字節(jié)碼指令通過從0開始的索引來使用其中的數(shù)據(jù),。 局部變量區(qū)對應(yīng)方法的參數(shù)和局部變量,。編譯器首先按聲明的順序把這些參數(shù)放入局部變量數(shù)組。 在java中,,所有的對象都按引用傳遞,,并且都存儲在堆中,永遠都不會在局部變量區(qū)或操作數(shù)棧中發(fā)現(xiàn)對象的拷貝,,只會有對象的引用,。 操作數(shù)棧:操作數(shù)棧也是被組織為一個字長為單位的數(shù)組。但它不是通過索引來訪問,,而是通過標(biāo)準(zhǔn)的棧操作——壓棧和出棧來訪問的,。 幀數(shù)據(jù)區(qū):支持解析常量池解析、正常方法返回以及異常派發(fā)機制,。每當(dāng)虛擬機要執(zhí)行某個需要用到常量池數(shù)據(jù)的指令時,,它都會通過幀數(shù)據(jù)區(qū)中指向常量池 的指針來訪問它。常量池中對類型,、字段和方法的引用在開始時都是符號,。當(dāng)虛擬機在常量池中搜索時,如果遇到類,、接口,、字段或者方法的入口,,假若它們?nèi)匀皇? 符號,虛擬機那時候才會進行解析,。 3.8執(zhí)行引擎 指令集:方法的字節(jié)碼流是由Java虛擬機的指令序列構(gòu)成的,。每一條指令包含一個單字節(jié)的操作碼,后面跟隨0個或多個操作數(shù),。操作碼本身就已經(jīng)規(guī)定了它是否需要跟隨操作數(shù),,以及如果有操作數(shù)它是什么形式的。當(dāng)虛擬機執(zhí)行一條指令的時候,,可能使用當(dāng)前常量池中的項,、當(dāng)前幀的局部變量中的值,或者當(dāng)前幀操作數(shù)棧頂端的值,。 執(zhí)行技術(shù):解釋,、即時編譯、字適應(yīng)優(yōu)化,、芯片級直接執(zhí)行。 Hotspot虛擬機就采用了自適應(yīng)優(yōu)化,。自適應(yīng)優(yōu)化虛擬機開始的時候?qū)λ械拇a都是解釋執(zhí)行,,但是它會監(jiān)視代碼的執(zhí)行情況。大多數(shù)程序花費80%-90%的時間來執(zhí)行10%-20%的代碼,。虛擬機可以意識到那些方法是程序的熱區(qū)——就是那10%-20%的代碼,,他們占整個執(zhí)行時間的80%-90%。當(dāng)自適應(yīng)優(yōu)化的虛擬機判斷出某個特定的方法是瓶頸的時候,,它啟動一個后臺線程,,把字節(jié)碼編譯成本地代碼,非常仔細(xì)的優(yōu)化這些本地代碼,。 |
|
來自: catph > 《java虛擬機筆記》