天天看點

從JVM 源碼看init和clinit到底什麼差別1 執行時機2 執行目的3 clinit詳解

JVM 源碼,都是初始化方法

從JVM 源碼看init和clinit到底什麼差別1 執行時機2 執行目的3 clinit詳解

1 執行時機

  • init是構造器時
  • clinit是類構造器時,也就是在類加載—–驗證—-解析—–初始化,中的初始化階段jvm調用clinit方法

2 執行目的

看 JVM 源碼:

從JVM 源碼看init和clinit到底什麼差別1 執行時機2 執行目的3 clinit詳解

is_static是啥?

從JVM 源碼看init和clinit到底什麼差別1 執行時機2 執行目的3 clinit詳解
  • init是instance執行個體構造器,對非靜态變量解析初始化
  • clinit是class類構造器對靜态變量,靜态代碼塊進行初始化

3 clinit詳解

準備階段,變量已經賦過一次系統要求的初始值

在初始化階段,則根據程式員通過程式制定的主觀計劃去初始化類變量和其他資源,或者可以從另外一個角度來表達:初始化階段是執行類構造器<clinit>方法的過程。

<clinit>方法是由編譯器自動收集類中的所有類變量的指派動作和靜态語句塊(static{}塊)中的語句合并産生的,編譯器收集的順序是由語句在源檔案中出現的順序所決定的,靜态語句塊中隻能通路到定義在靜态語句塊之前的變量,定義在它之後的變量,在前面的靜态語句塊可以指派,但是不能通路

從JVM 源碼看init和clinit到底什麼差別1 執行時機2 執行目的3 clinit詳解

虛拟機會保證在子類的<clinit>方法執行之前,父類的<clinit>方法已經執行完畢。

是以在虛拟機中第一個被執行的<clinit>方法的類肯定是java.lang.Object。意味着父類中定義的靜态語句塊要優先于子類的變量指派操作

接口中不能使用靜态語句塊,但仍有變量初始化的指派,是以接口與類一樣都會生成<clinit>方法。

不同的是,執行接口的<clinit>方法不需要先執行父接口的<clinit>方法。 隻有當父接口中定義的變量使用時,父接口才會初始化。

另外,接口的實作類在初始化時也一樣不會執行接口的<clinit>方法。

接口中的屬性都是static final類型的常量,是以在準備階段就已經初始化