java虛擬機器類

來源:互聯網
上載者:User

標籤:src   orm   修改   命名空間   語句   方法   其他   需要   pat   

java虛擬機器中類的載入

            (JVM的大致結構圖)

從發class檔案到記憶體中的類,按先後順序,需要經過載入,連結以及初始化三大步驟。

java語言的類型可分為兩大類:基本類型(primitive type)和參考型別(references type)

 

基本類型:是由java虛擬機器預先定義好的。

參考型別:Java將其細分為四種,類、介面、數組類和泛型參數。

       由於泛型參數會在編譯過程中被擦除(泛型型別在邏輯上可以看成是多個不同的類型,實際上都是相同的基本類型。),因此Java虛擬機器實際上只有前三種。在類、介面和數組類中,數組類是由java虛擬機器直接產生的,其他兩種則有對應的位元組流。

位元組流:最常見的形式要屬由Java編譯器產生的class檔案。除此之外,我們也可以在程式內部直接產生,或者從網路中擷取位元組流。這些不同形式的位元組流,都會被載入到java虛擬機器中,稱為類或者介面。

 

無論是直接產生的數組類,還是載入的類,java虛擬機器都要對其進行連結和初始化。

 

載入

載入是指尋找位元組流,並且據此建立類的過程。對於類來說,java虛擬機器需要藉助類載入器來完成尋找位元組流的過程。

 當JVM啟動時,會形成由三個類載入器組成的初始類載入器階層:

1、啟動類載入器(BootstrapClassLoader):是嵌在JVM核心中的載入器,它是由C++實現的,沒有對應的java對象,因此在java中只能用null來代替。它主要負責載入JAVA_HOME/lib下的類庫,啟動類載入器無法被應用程式直接使用。

除了啟動類載入器外,其他的類載入器都是java.lang.ClassLoader的子類,因此有對應的java對象。這些類載入器需要先由另一個類載入器,比如說啟動了載入器,載入至java虛擬機器中,方能執行類載入。

 

在Java9之前,啟動類載入器負責載入最為基礎,最為重要的類,比如存放在jre的lib目錄下的jar包(以及由虛擬機器參數-Xbootclasspath指定的類)。除了啟動類載入器之外,另外兩個重要的類載入器是擴充類載入起(extension class loader)和應用類載入器(application class loader),均由java核心類庫提供。

2、擴充類載入器(extension class loader):其父類是啟動類載入器,他負責載入相對次要、但又通用的類,比如存放在jre的lib/ext目錄下的jar包中的類(以及由系統變數java.ext.dirs指定的類)。

3、應用類載入器(application class loader):其父類是擴充類載入器,它負責載入用用程式下的類。(這裡的應用程式路徑,便是指虛擬機器參數-cp/-classpath、系統變數CLASSPATH所制定的路徑。)預設情況下,應用程式中包含的類是由應用類載入器載入的。

java9引入了模組系統,,並且略微更改了上述的類載入器,擴充類載入器被改名為平台類載入器(platform class loader)。Java SE 中除了少數幾個關鍵模組,比如說、java.base是由啟動類載入器載入之類,其他的模組均由平台載入器所載入。

 

除了java核心類庫提供的類載入器之外,我們還可以加入自訂的載入器,來實現特殊的載入方式。舉個例子,我們可以對class檔案進行加密,載入時再利用自訂的類載入最其解密。

 

除了載入功能之外,類載入器還提供了命名空間的作用。在java虛擬機器中,類的唯一性是由類載入器執行個體以及類的全名一同確定的。即便是通一串位元組流,經由不同的類載入器載入,也會得到兩個不同的類。在大型應用中,我們往往會藉助這一特性,來運行同一個類的不同版本。

 

連結

連結是指將建立成的類合并至java虛擬機器中,使之能執行的過程。它可以分為驗證、準備及解析三個階段。

驗證:確保被載入的類能夠滿足java虛擬機器的約束條件,檢驗被載入的類是否有正確的內部結構,並和其他類協調一致。

準備:為被載入類的靜態欄位分配記憶體,並設定預設初始值。

解析:將類中的位元據中的符號引用替換成直接引用(final修改的常量的替換)。

JVM並沒有要你在連結過程中完成解析,它僅規定了:如果某些位元組碼使用了符號引用,那麼在執行這些位元組碼之前,需要完成對這些符號引用的解析。

 

初始化

在java代碼中如果要初始化一個靜態欄位,我們可以在聲明時直接賦值,也可以在靜態代碼塊中對其賦值。

如果直接賦值的靜態欄位被final修飾,並且他的類型是基本類型或字串時,那麼該欄位便會被java編譯器標記為常量值(ConstantValue),其初始化直接被java虛擬機器完成。除此之外的直接賦值操作以及所有靜態代碼塊中的代碼,則會被java編譯器置於同一方法中,並把它命名為<clinit>。

類載入的最後一步是初始化,便是為標記為常量值的欄位賦值,以及執行<clinit>方法的過程。java虛擬機器會通過加鎖來確保類的<clinit>方法僅被執行一次。

只有當初始化完成之後,類才正式稱為可執行檔狀態。

JVM初始化一個類分為幾步:

1、假如這個類還沒有被載入和連結,程式先載入並連結這個類。

2、假如該類的直接父類還沒有被初始化,則先初始化其直接父類。

3、假如類中有初始化語句,則依次執行其初始化語句。

 

類的載入和初始化何時被觸發

 

1、當虛擬機器啟動時,初始化使用者指定的主類。(直接使用java.exe命令來運行某個主類)

2、建立類的執行個體(new方法)。

3、調用某個類的靜態方法,初始化該靜態方法所在的類。

4、訪問某個類或介面的靜態屬性,初始化該靜態屬性所在的類。

5、使用反射機制來建立某個類或介面的對應java.lang.Class對象(Class.forName("Person")),初始化這個類。

6、子類的初始化會觸發父類的初始化。

7、如果一個介面定義了default方法,那麼直接實現或間接實現該介面的類的初始化,會觸發該介面的初始化。

8、當初次使用MehodHandle執行個體時,初始化該MehodHandle指向的方法所在的類。

 

註:此文為極客時間鄭雨迪專欄,java虛擬機器講解及自己查資料的學習總結。鄭雨迪《深入拆解Java虛擬機器》很不錯。

 

java虛擬機器類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.