摘要:驗證過程驗證過程的目的是為了確保文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。二虛擬機字節碼執行引擎虛擬機的執行引擎自行實現,可以自行制定指令集與執行引擎的結構體系。
本篇博客主要針對Java虛擬機的類加載機制,虛擬機字節碼執行引擎,早期編譯優化進行總結,其余部分總結請點擊Java虛擬總結上篇 。
一.虛擬機類加載機制 概述虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。
類加載的時機類加載的時機不止一種:
遇到new等字節碼指令時會進行類加載
反射調用時會進行類加載
在初始化時,若待初始化的類有父類則其父類先進行初始化(接口除外),并且先初始化包含main的主類。需要注意的是子類引用父類非final靜態變量時,只初始化靜態變量所在類,即父類,而引用final類型static變量不會引起任何初始化,因為其編譯期間就已經儲存在常量池中了。另外數組定義也是不會引發類的初始化。比如
Student[] stus=new Student[10];
是不會引起Student類的初始化的。
類加載的過程 加載過程通過類的全限定名來獲取定義此類的二進制字節流,將這個字節流所代表的靜態存儲結構轉換為方法區的運行時數據結構,在內存中生成一個代表類的數據訪問入口的java.lang.Class對象。
驗證過程驗證過程的目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。主要有
文件格式驗證:驗證魔數,主次版本號,常量類型等。
元數據驗證:是否有父類,是否繼承了不該繼承的類,抽象類是否實現了方法等。
字節碼驗證:確保程序語義是合法的,符合邏輯的。如類型轉換,跳轉指令等。
符號引用驗證:對類自身以外的信息(常量池中的各種引用)進行匹配校驗。
準備過程正式為類變量分配內存并設置類變量初始值的階段,只包括類變量而不包括實例變量和final類變量,而且僅僅只是初始化為0值。
解析過程虛擬機將常量池內的符號引用轉換為直接引用的過程。符號引用用一組符號來描述所引用的目標。而直接引用是直接指向目標的指針,相對偏移量或是一個能間接定位到目標的句柄。
初始化階段在初始化階段真正開始執行Java程序代碼(字節碼),執行類的構造器
實現通過一個類的全限定名獲取描述此類的二進制字節流的代碼模塊稱為類加載器。比較兩個類是否相等,一定是在同一個類加載器的前提下進行的,否則哪怕Class文件都一樣也不相等
類加載器的分類啟動類加載器, 負責將存放在
擴展類加載器,負責加載
應用程序類加載器,負責加載用戶類路徑(classpath)上的指定類庫,我們可以直接使用這個類加載器。一般情況,如果我們沒有自定義類加載器默認就是用這個加載器。
雙親委派模型雙親委派模型工作過程是:如果一個類加載器收到類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器完成。每個類加載器都是如此,只有當父加載器在自己的搜索范圍內找不到指定的類時(即ClassNotFoundException),子加載器才會嘗試自己去加載。
這樣做的好處是Java類隨著它的類加載器一起具備了一種帶有優先級的層次關系。
二.虛擬機字節碼執行引擎虛擬機的執行引擎自行實現,可以自行制定指令集與執行引擎的結構體系。
棧幀棧幀是用于支持虛擬機進行方法調用和方法執行的數據結構,是虛擬機棧的棧元素。它儲存了方法的局部變量表,操作數棧,動態鏈接,方法返回地址,對于活動線程來說,只有棧頂的棧幀才是有效的,稱為當前棧幀,與其關聯的方法叫做當前方法。
局部變量表局部變量表存放方法參數和方法內部定義的變量。單位是slot(槽),最大可以達到32位。垃圾回收時,slot可以復用,將不使用的變量置為null是有意義的,方便垃圾回收。局部變量不像類變量,是沒有初始值的。
JIT編譯器當虛擬機發現某個方法或代碼塊運行特別頻繁時,就會把這些代碼認定為 “Hot Spot Code”(熱點代碼),為了提高熱點代碼的執行效率,在運行時,虛擬機將會把這些代碼編譯成與本地平臺相關的機器碼,并進行各層次的優化,完成這項任務的正是 JIT 編譯器。
方法返回地址遇到方法的返回指令-->正常完成出口
遇到異常并且未處理-->異常完成出口,不會給上層調用者產生任何返回值
方法調用方法在編譯時并不確定方法的真實地址,而是一個符號引用,使得Java的動態擴展能力提升,在類加載過程甚至運行時才確定目標方法的直接引用。
解析在類的解析階段將一部分符號引用轉換為直接引用,這部分符號引用代表的方法必須“編譯期可知,運行時不變”,如靜態方法,私有方法,實例構造器,父類方法。final方法也是。
分派靜態分派(與重載相關),依賴靜態類型來定位方法執行版本的分派動作。自動轉型順序:char->int->long->float->double->Character->Serializable->Object->char...
動態分派(重寫相關),找到操作數棧頂的第一個元素所指向的對象的實際類型,若常量池中的描述符和簡單名稱都相符,則返回直接引用,否則對其父類進行第二步。
動態分配的實現:
在類的方法區建立一個虛方法表提升效率,若子類未重寫父類的方法,則子類的繼承方法中地址和父類方法的地址是一樣的,若重寫了父類的方法,則子類的方法地址就會改變,指向自己實現的版本。如上圖Son的clone方法沒有被重寫,指向的是Object父類的地址,而hardChoice方法被重寫了,指向的是Son自己實現的地址。
動態類型語言類型檢查的主題過程在運行期而不是在編譯期,如Python,Javascript,Ruby,PHP,與之相對的就是靜態語言。
解釋執行與編譯執行解釋執行為邊解釋邊執行,編譯執行則是先將源代碼編譯成目標語言 (如: 機器語言) 之后通過連接程序連接到生成的目標程序進行執行。
基于棧的字節碼解釋執行引擎基于棧的指令集:Java編譯器輸出的指令流
基于寄存器的指令集:x86匯編
三.早期編譯器優化 編譯器三種編譯器:
前端編譯器:把.java變成.class的過程,eg:Javac
后端運行期編譯器(JIT):把字節碼變成機器碼的過程,eg:Hotpot的C1,C2編譯器
靜態提前編譯器(AOT):直接把*.java變成機器碼的過程,eg:GCJ(GNU Compiler for the Java)
解析與填充符號表 詞法分析標記是編譯過程的最小元素,關鍵字、變量名、字面量、運算符都可以成為標記,詞法分析就是將源代碼的字符流轉變為標記集合。
語法分析語法分析是根據Token序列構造抽象語法樹的過程。抽象語法樹是用來描述程序代碼語法結構的樹形表示方法,每一個節點都代表著程序代碼的一個語法結構:包,類型,修飾符等。
注解處理器類似編譯器的一種插件,如果插件對語法樹進行了修改,編譯器將回到解析及填充符號表的過程重新處理。
語義分析對語法抽象樹進行上下文有關性質的審查,如類型檢查。
字節碼生成將前面各個步驟生成的信息轉換成字節碼寫到磁盤中,類構造器
泛型與類型擦除:與C#不一樣,Java的泛型是偽泛型,在生成的字節碼中已經被替換成了原生類型了,會自動加上類型轉換。
遍歷:自動轉換為iterator遍歷。
裝箱與拆箱:==運算在不遇到算數運算的情況下不會自動拆箱。equals方法不會處理數據的類型轉換,而==會。
條件編譯編譯器不會編譯if到達不到的語句,也就是取消分支不成立的代碼塊,可以查看反編譯后的代碼驗證條件編譯。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68645.html
摘要:于是這篇博客就針對虛擬機的各個知識點進行歸納。若虛擬機棧請求擴展時無法申請到足夠的內存,則拋出異常。類索引用于確定類的全限定名,父類索引用于確定父類的全限定名。字節碼指令操作碼長度為一個字節,所以總數最多不超過條。 Java虛擬機一直是Java的重難點,一方面由于系統封裝得太好,你平常寫程序的時候幾乎感覺不到它的存在,另一方面了解必要的Java虛擬機工作原理才能對真實工作環境下的bug...
摘要:本篇博客主要針對虛擬機的晚期編譯優化,內存模型與線程,線程安全與鎖優化進行總結,其余部分總結請點擊虛擬總結上篇,虛擬機總結中篇。 本篇博客主要針對Java虛擬機的晚期編譯優化,Java內存模型與線程,線程安全與鎖優化進行總結,其余部分總結請點擊Java虛擬總結上篇 ,Java虛擬機總結中篇。 一.晚期運行期優化 即時編譯器JIT 即時編譯器JIT的作用就是熱點代碼轉換為平臺相關的機器碼...
摘要:與都繼承自類,在中也是使用字符數組保存字符串,,這兩種對象都是可變的。采用字節碼的好處語言通過字節碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。 String和StringBuffer、StringBuilder的區別是什么?String為什么是不可變的? String和StringBuffer、StringBuilder的區別 可變性...
摘要:最近在備戰面試的過程中,整理一下面試題。成員變量如果沒有被賦初值,則會自動以類型的默認值而賦值一種情況例外被修飾但沒有被修飾的成員變量必須顯示地賦值而局部變量則不會自動賦值。 最近在備戰面試的過程中,整理一下面試題。大多數題目都是自己手敲的,網上也有很多這樣的總結。自己感覺總是很亂,所以花了很久把自己覺得重要的東西總結了一下。 面向對象和面向過程的區別 面向過程: 優點:性能比面...
閱讀 3080·2021-11-24 10:47
閱讀 3831·2021-11-02 14:43
閱讀 2228·2021-09-26 10:15
閱讀 2253·2021-09-08 09:35
閱讀 560·2019-08-30 12:45
閱讀 2781·2019-08-29 17:04
閱讀 3214·2019-08-26 14:05
閱讀 1259·2019-08-26 12:10