1. 程式人生 > >java 類載入機制--類載入時機

java 類載入機制--類載入時機

相對於看很多父類和子類如何如何初始化的文章,瞭解java虛擬機器的類載入機制之後都會覺得,噢,原來是這個樣子!這裡僅就類的載入時機做個學習筆記,更多內容改日再寫。詳情請看《深入理解java虛擬機器》。

不同於例如c,cpp那些編譯時期就需要進行連線工作的語言,在java裡面,型別的載入,連線和初始化過程都可以在程式執行期間完成,雖然稍微增加了效能開銷,但是會為java應用程式提供高度的靈活性。java裡可以天生可以動態擴充套件的特性就是依賴執行期載入和動態連線這個特點實現的。
類的整個生命週期包括:載入(loading),驗證(verification),準備(preparation),解析(resolution),初始化(initialization),使用(using)和解除安裝(unloading) 7個階段。其中驗證,準備和解析3個部分統稱為連線(linking)。

載入,驗證,準備,初始化和解除安裝這五個階段的順序是確定的,類的載入過程必須按照這個順序進行,而解析階段則不一定,為了支援 java 的執行時繫結(也稱動態繫結或者晚期繫結),它有時可以在初始化階段之後再開始。

那麼就要問了,什麼時候開始類載入的第一階段,也就是載入階段?這一點在 java 虛擬機器規範中沒有強制約束,可以有虛擬機器自己實現。

但是對於初始化階段,java 虛擬機器規範做了嚴格的規定,而載入,驗證,準備自然需要在初始化之前開始。

初始化觸發條件

  1. 遇到 new , getstatic , putstatic , invokestatic 這四條位元組碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。這幾個位元組碼分別代表著幾個意思:

    • new : 使用 new 關鍵字例項化一個物件的時候。
    • getstatic putstatic : 讀取或者設定一個類的靜態變數 (被 final 修飾的在編譯期被寫入常量池的除外)
    • invokestatic : 呼叫一個類的靜態方法
  2. 使用 java.lang.reflect 包的方法對類進行反射呼叫時,如果類還沒有進行初始化。

  3. 當初始化一個類時,發現他的父類還沒有進行初始化,則先出發其父類的初始化。

  4. 虛擬機器啟動時,使用者需要指定一個要執行的主類,也就是包含 mian 方法的那個類,虛擬機器會先初始化這個類。

  5. 使用 jdk 1.7 時,如果一個 java.lang.invoke.MethodHandle 例項最後的解析結果是 REF_getStatic , REF_putStatic , REF_invokeStatic 的方法控制代碼,並且這個方法對應得類沒有進行過初始化,則需要先出發其初始化。

對於這五種會觸發類初始化的場景,虛寂寂規範中使用了一個很強的限定語:”有且只有“。這物種場景中的行為被稱為對一個類的主動引用。除此之外,所有引用類的方式都不會出發初始化,稱為被動引用。

不會觸發類的初始化的被動引用的例子:

  1. 通過子類引用父類的靜態欄位,不會導致子類的初始化。

    至於是否會觸發子類的載入和驗證,並沒有明確規定,取決於虛擬機器的實現,對於 Sun HotSpot 虛擬機器,可以通過 -XX:+TraceClassLoading 引數觀察到子類的載入。

  2. 通過陣列定義來引用類,不會出發此類的初始化。

    例如:Person[] persons=new Person[2]

    虛擬機器會自動載入一個 Person 類的全類名最前面再加個 L 的類,直接繼承於 java.lang.Object ,建立動作由 newarray 位元組碼觸發。陣列中應有的屬性和方法(使用者可以直接使用的只有被修飾為 public 的 length 屬性和 clone() 方法)都實現在這個類裡。java 語言對陣列的訪問更為安全就是因為這個類封裝了陣列元素的訪問方法。當檢測到陣列越界時會丟擲 java.lang.ArrayIndexOutOfBountsException 異常。

  3. 常量在編譯階段會存入呼叫類的常量池中,本質上並沒有直接引用到定義常量的類,兩個類在編譯之後不再有聯絡,因此不會觸發類的初始化。

介面的載入過程和類稍微有點不同,介面也有初始化過程,這點和類一樣。介面和類的區別就是前面講述的五種需要初始化場景的第三種:當一個介面在初始化時,並不要求其父介面都完成初始化,只有在真正使用到父介面時,(如引用介面中定義的常量)才會初始化。

相關推薦

java 載入機制--載入時機

相對於看很多父類和子類如何如何初始化的文章,瞭解java虛擬機器的類載入機制之後都會覺得,噢,原來是這個樣子!這裡僅就類的載入時機做個學習筆記,更多內容改日再寫。詳情請看《深入理解java虛擬機器》。 不同於例如c,cpp那些編譯時期就需要進行連線工作的語言,

虛擬機器載入機制——載入時機

文章目錄 一、類載入(初始化)的時機 二、主動引用、被動引用及被動引用的幾個例子 2.1 通過子類引用父類的靜態欄位,不會導致子類的初始化 2.2 通過陣列定義引入類,不會觸發類的初始化 2.3 訪問用final修飾的靜態欄位,不會

java載入機制以及載入模型

1、概述 我們先來看下下面的java程式碼:(大家感覺會輸出什麼結果呢?) public class TestClass { static { System.out.println("TestClass"); } publi

虛擬機器載入機制——載入的過程

文章目錄 一、載入 二、連線之驗證 三、連線之準備 四、連線之解析 4.1 準備工作 4.2 類或介面解析 4.3 欄位解析 4.4 類方法解析 4.5 介面方法解析 五、初始化

JVM的載入機制載入過程

一、虛擬機器的類載入機制    虛擬機器把描述類的資料從Class檔案載入到記憶體,並對資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別。這就是虛擬機器的類載入機制。    與那些在編譯器需要進行連線工作的語言不同,在Java語言中,型別的載入和連

[Java 15 反射機制 ] 的生命週期 與 反射總結

15.6 類的生命週期    在一個類編譯完成之後,下一步就要開始使用類,如果要使用一個類,離不開JVM。在程式執行中 JVM 通過 裝載,連結,初始化 3個步驟完成,類的裝載就是通過類載入器把 *.class 檔案裝入 JVM 的方法區,並在堆區建立描述該類的 java

虛擬機器載入機制之類載入

文章目錄 一、在虛擬機器中,類的唯一性是怎樣確保的。 二、雙親委派模型 三、破壞雙親委派模型 在類的載入過程中的載入階段,我們使用到了類載入器。 一、在虛擬機器中,類的唯一性是怎樣確保的。 在虛擬機器中,是通過載入類的

《深入理解Java虛擬機器》個人讀書總結——虛擬機器載入機制

我們都知道Java虛擬機器是用來執行我們編譯好的.class檔案的,class檔案中夾帶類的各種資訊,虛擬機器要執行這些檔案,第一件事就是要載入到虛擬機器中,這就引出了這次總結的問題——虛擬機器是如何載入這些class檔案的?載入後虛擬機器是怎麼處理檔案中夾帶的資訊的? 類載入機制

從阿里巴巴面試題到java載入機制

首先很經典的阿里巴巴面試題 加上我自己的一些疑惑程式碼 public class Text { public static int k = 0; public final int k1 = 3; //自己加的 public static Text t1 = new Text("

java虛擬機器載入機制學習

1、什麼是類的載入 類的載入指的是將類的.class檔案中的二進位制資料讀入到記憶體中,將其放在執行時資料區的方法區內,然後在堆區建立一個java.lang.Class物件,用來封裝類在方法區內的資料結構。類的載入的最終產品是位於堆區中的Class物件,Class物件封裝了類在方法區內的資料結構

java機制:載入詳解(靜態,靜態變數,靜態方法,靜態程式碼塊,構造程式碼塊,成員變數,成員方法,父...)

       “程式碼編譯的結果從本地機器碼轉變為位元組碼,是儲存格式發展的一小步,卻是變成語言發展的一大步”,這句話出自《深入理解JAVA虛擬機器》 一.原始碼編譯      &n

java載入機制和自定義載入

類載入順序 上圖所示的是類載入的順序,按照大的順序可以分為載入、連結、初始化 其中連結又可以分成驗證、準備、解析三個步驟 載入 1.將類的class檔案讀入到記憶體中 載入類檔案的方式有: 1. 本機檔案載入 2.jar包載入 3.網路載入 4.原始檔動態編譯載入

java中的載入機制

今天看了許多大牛的解釋,現在來做個總結: 類的載入機制過程是指由jvm的類載入器載入class位元組碼檔案進入記憶體的過程;(暫且這樣理解) 類載入器可以分為引導類載入器,擴充套件類載入器,系統類載入器;有些地方又可以這樣分:啟動類載入器,自定義載入器。 類載入機制過程:

JAVA虛擬機器(七)虛擬機器載入機制

虛擬機器的類載入機制是指 把描述類的資料從Class檔案載入到記憶體,並對資料進行校驗,轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別。類的載入連線和初始化過程都是在程式執行期間完成的。 類的生命週期: 載入->連線(驗證,準備,解析)->初始化->使用

Java虛擬機器載入機制經典案例

package io.lgxkdream.test; class Father { static Father f = new Father(); static { System.out.println("father-1"); } { System.out.println("

深入java虛擬機器(二) 載入機制/生命週期

一、類的載入時機 類從被載入到虛擬機器到解除安裝為止,整個生命週期包括:載入、校驗、準備、解析、初始化、使用、解除安裝這幾個過程,其中校驗、準備、解析這三個過程又稱為初始化。嚴格意義上講這幾個過程並不是按部就班的進行,也會有相互交叉進行,尤其是校驗過程,也可能是在初始化階段之後再開始。

java學習記錄-載入機制

類載入機制主要分3塊:類載入器(ClassLoader)、類載入過程和雙親委託(破壞雙親委託)   類載入器:是Java執行時環境(Java Runtime Environment)的一部分,負責動態載入Java類到Java虛擬機器的記憶體空間中。jdk自帶了三種類載入器,分別是引導類載入器(B

《深入理解java虛擬機器》讀書筆記(一)---- 載入機制

類載入的時機 1、類從虛擬機器載入到記憶體開始,到卸載出記憶體為止,整個生命週期分為七個階段:載入、驗證、準備、解析、初始化、使用和解除安裝。其中驗證、準備和解析統稱為連線階段。 2、載入、驗證、準備、初始化和解除安裝這五個階段是按順序執行的,而解析階段卻不一定,解析可以在初始化之後

深入理解Java虛擬機器筆記——虛擬機器載入機制

虛擬機器類載入機制 類載入機制:虛擬機器把描述類的資料從class檔案載入到記憶體,並對資料進行校驗、  轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別。 在Java中,型別的載入和連線過程都是在程式執行期間完成的。   類載入時機(類從載入到虛擬

Java虛擬機器:載入機制詳解

    大家知道,我們的Java程式被編譯器編譯成class檔案,在class檔案中描述的各種資訊,最終都需要載入到虛擬機器記憶體才能執行和使用,那麼虛擬機器是如何載入這些class檔案的呢?在載入class檔案的過程中虛擬機器又幹了哪些事呢?今天我們來解密虛擬機器的類載入機制。