jvm虛擬機筆記<三> 類文件結構與類載入機制

来源:https://www.cnblogs.com/lvoooop/archive/2019/12/04/11985086.html
-Advertisement-
Play Games

java虛擬機具有語言無關係,它只和“class文件“這種特定的二進位文件格式綁定。 不同語言的編譯器將對應的程式編譯成位元組碼文件(*.class),送給jvm執行。 2.1、魔數(是否可以被虛擬機執行)和class文件版本 2.2、常量池 2.3、訪問標誌(識別訪問信息) 2.4、類索引、父類索引 ...


java虛擬機具有語言無關係,它只和“class文件“這種特定的二進位文件格式綁定。

不同語言的編譯器將對應的程式編譯成位元組碼文件(*.class),送給jvm執行。

  • 2.1、魔數(是否可以被虛擬機執行)和class文件版本
  • 2.2、常量池
  • 2.3、訪問標誌(識別訪問信息)
  • 2.4、類索引、父類索引和介面索引集合
  • 2.5、欄位表集合
  • 2.6、方法表集合

————————————————————————————————————————————————

一.類載入時機:

共5種情形為主動引用,有且僅有此5種會觸發初始化,其他方式全部為被動引用,不會觸發類的初始化

5種情形:

  • 遇到new (實例化對象),getstatic(讀取一個類的靜態欄位) ,putstatic(設置一個類的靜態欄位), invokestatic(調用一個類的靜態方法)這4條指令,若類之前沒有初始化,需要先對其進行初始化。
  • 使用 java.lang.reflect包的方法對類進行反射調用時,若類之前沒有初始化,需要先對其進行初始化。
  • 當初始化一個類,其父類之前沒有初始化,需要先對其父類進行初始化。
  • 當虛擬機啟動時,主類會先被初始化(包含main方法的類)。
  • 使用jdk7的動態語言支持時,如果一個解析結果與靜態欄位或靜態方法有關,所對應的類之前沒有初始化,需要先對其進行初始化。

二.類載入過程

 

 其中類載入的過程包括了載入、驗證、準備、解析、初始化五個階段。

在這五個階段中,載入、驗證、準備和初始化這四個階段發生的順序是確定的,而解析階段則不一定,它在某些情況下可以在初始化階段之後開始,這是為了支持Java語言的運行時綁定(動態綁定)。

另外註意這裡的幾個階段是按順序開始,而不是按順序進行或完成,因為這些階段通常都是互相交叉地混合進行的,通常在一個階段執行的過程中調用或激活另一個階段。

1.載入

  載入過程完成一下3件事:

  • 獲取一個類全限定名的二進位位元組流。
  • 將靜態存儲結構轉換為方法區的運行時數據結構
  • 記憶體中生產class對象,作為方法區中該類的數據訪問入口

  載入與連接階段交叉進行(但是開始時間順序固定)。

2.驗證

  四個階段:文件格式驗證(驗證規範),元數據驗證(語義校驗),位元組碼驗證(數據流與控制流分析),符號引用認證(符號引用的匹配校驗)。

3.準備:正式分配記憶體並設置變數初始值,記憶體在方法區內分配。

4.解析:將常量池內的符號引用替換為直接引用

  符號引用:一組可以無歧義定位到目標的符號

  直接引用:直接指向目標的指針,相對偏移量或者能間接定位到目標的句柄

5.初始化:根據程式制定的主管計划去初始化變數與資源。

三.類載入器

1.類與類載入器。每一個類載入器都有其獨立的類名稱空間,兩個類由同一個類載入器載入才可能相同,否則必然不同(equals,isAssignableFrom,isInstance)

2.雙親委派機制。

類載入器負責載入所有的類,其為所有被載入記憶體中的類生成一個java.lang.Class實例對象。一旦一個類被載入如JVM中,同一個類就不會被再次載入了。正如一個對象有一個唯一的標識一樣,一個載入JVM的類也有一個唯一的標識。在Java中,一個類用其全限定類名(包括包名和類名)作為標識;但在JVM中,一個類用其全限定類名和其類載入器作為其唯一標識。例如,如果在pg的包中有一個名為Person的類,被類載入器ClassLoader的實例kl負責載入,則該Person類對應的Class對象在JVM中表示為(Person.pg.kl)。這意味著兩個類載入器載入的同名類:(Person.pg.kl)和(Person.pg.kl2)是不同的、它們所載入的類也是完全不同、互不相容的。

JVM預定義有三種類載入器,當一個 JVM啟動的時候,Java開始使用如下三種類載入器:

            

1)根類載入器(bootstrap class loader):它用來載入 Java 的核心類,是用原生代碼來實現的,並不繼承自 java.lang.ClassLoader(負責載入$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++實現,不是ClassLoader子類)。由於引導類載入器涉及到虛擬機本地實現細節,開發者無法直接獲取到啟動類載入器的引用,所以不允許直接通過引用進行操作。

2)擴展類載入器(extensions class loader):它負責載入JRE的擴展目錄,lib/ext或者由java.ext.dirs系統屬性指定的目錄中的JAR包的類。由Java語言實現,父類載入器為null。

3)系統類載入器(system class loader):被稱為系統(也稱為應用)類載入器,它負責在JVM啟動時載入來自Java命令的-classpath選項、java.class.path系統屬性,或者CLASSPATH換將變數所指定的JAR包和類路徑。程式可以通過ClassLoader的靜態方法getSystemClassLoader()來獲取系統類載入器。如果沒有特別指定,則用戶自定義的類載入器都以此類載入器作為父載入器。由Java語言實現,父類載入器為ExtClassLoader。

類載入器載入Class大致要經過如下8個步驟:

  1. 檢測此Class是否載入過,即在緩衝區中是否有此Class,如果有直接進入第8步,否則進入第2步。
  2. 如果沒有父類載入器,則要麼Parent是根類載入器,要麼本身就是根類載入器,則跳到第4步,如果父類載入器存在,則進入第3步。
  3. 請求使用父類載入器去載入目標類,如果載入成功則跳至第8步,否則接著執行第5步。
  4. 請求使用根類載入器去載入目標類,如果載入成功則跳至第8步,否則跳至第7步。
  5. 當前類載入器嘗試尋找Class文件,如果找到則執行第6步,如果找不到則執行第7步。
  6. 從文件中載入Class,成功後跳至第8步。
  7. 拋出ClassNotFountException異常。
  8. 返回對應的java.lang.Class對象。

四、類載入機制:

1.JVM的類載入機制主要有如下3種。

  • 全盤負責:所謂全盤負責,就是當一個類載入器負責載入某個Class時,該Class所依賴和引用其他Class也將由該類載入器負責載入,除非顯示使用另外一個類載入器來載入。
  • 雙親委派:所謂的雙親委派,則是先讓父類載入器試圖載入該Class,只有在父類載入器無法載入該類時才嘗試從自己的類路徑中載入該類。通俗的講,就是某個特定的類載入器在接到載入類的請求時,首先將載入任務委托給父載入器,依次遞歸,如果父載入器可以完成類載入任務,就成功返回;只有父載入器無法完成此載入任務時,才自己去載入。
  • 緩存機制。緩存機制將會保證所有載入過的Class都會被緩存,當程式中需要使用某個Class時,類載入器先從緩存區中搜尋該Class,只有當緩存區中不存在該Class對象時,系統才會讀取該類對應的二進位數據,並將其轉換成Class對象,存入緩衝區中。這就是為很麽修改了Class後,必須重新啟動JVM,程式所做的修改才會生效的原因。

2雙親委派機制:

雙親委派機制,其工作原理的是,如果一個類載入器收到了類載入請求,它並不會自己先去載入,而是把這個請求委托給父類的載入器去執行,如果父類載入器還存在其父類載入器,則進一步向上委托,依次遞歸,請求最終將到達頂層的啟動類載入器,如果父類載入器可以完成類載入任務,就成功返回,倘若父類載入器無法完成此載入任務,子載入器才會嘗試自己去載入,這就是雙親委派模式,即每個兒子都很懶,每次有活就丟給父親去乾,直到父親說這件事我也幹不了時,兒子自己才想辦法去完成。

雙親委派機制的優勢:採用雙親委派模式的是好處是Java類隨著它的類載入器一起具備了一種帶有優先順序的層次關係,通過這種層級關可以避免類的重覆載入,當父親已經載入了該類時,就沒有必要ClassLoader再載入一次。其次是考慮到安全因素,java核心api中定義類型不會被隨意替換,假設通過網路傳遞一個名為java.lang.Integer的類,通過雙親委托模式傳遞到啟動類載入器,而啟動類載入器在核心Java API發現這個名字的類,發現該類已被載入,並不會重新載入網路傳遞的過來的java.lang.Integer,而直接返回已載入過的Integer.class,這樣便可以防止核心API庫被隨意篡改。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Nio與IO的區別 原有的 IO 是面向流的、阻塞的,NIO 則是面向塊的、非阻塞的。 1.IO流每次從流中讀一個或多個位元組,直至讀完所有位元組,他們沒有被緩存在其他地方,並且,IO流不能移動流中的數據,如果需要前後移動從流中讀取的教據,需要先將它緩存到一個緩衝區。Java NIO的緩衝導向方法略有不 ...
  • 幾個常用的對象 Workbook:工作簿,一個包含多個Sheet的Excel文件 Worksheet:工作表,一個Workbook有多個Worksheet,如“Sheet1”,“Sheet2”等 Cell:單元格,存儲具體的數據對象 導入包 創建Workbook、Worksheet 寫入數據 保存 ...
  • 上面這種方法“無論如何”都讀不出f的內容,使用readlines和迴圈也不行。 但是,用以下的方法,卻可以“正常讀取”: 這是為什麼呢? PS:遇到問題沒人解答?需要Python學習資料?可以加點擊下方鏈接自行獲取 note.youdao.com/noteshare?id=2dce86d0c2588 ...
  • 使用VSCode + NET Core3.0在ASP.NET Core中使用Web API創建 RESTful 服務,包括創建簡單Rest API、格式化輸出、JSON Patch請求、Open API(Swagger)集成 ...
  • asp.net core 從 3.0 到 3.1 Intro 今天 .net core 3.1 正式發佈了,.net core 3.1 正式版已發佈,3.1 主要是對 3.0 的 bug 修複,以及一些小優化,而且作為 LTS 版本,建議大家升級。值得一提的是.net core 2.2 這個月就要壽 ...
  • 目 錄 1. 概述... 2 2. 演示信息... 2 3. 簡單介紹... 3 4. 產品特點... 4 5. 價值體現... 5 1. 概述 經過一段時間的努力,iNeuDA產品組件已經開發和測試完成,現在正式上線。現在iNeuOS工業互聯網操作系統的技術體系和產品體系更佳完善,為中小企業提供更 ...
  • Net Core 2.x 跟 Net Core3.0 還是有很大的區別的,隨著.NET Core 3.1發佈,也就意味著老版本慢慢的要停止維護。 Net Core 3.0 其實就是過渡版本,用於我們練手。 ASP.NET Core 2.2 遷移到3.0:https://docs.microsoft. ...
  • 參考博客: https://blog.csdn.net/flyer_tang/article/details/80320974 https://blog.csdn.net/weixin_30773135/article/details/97923338 官網下載地址: http://redis.io ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...