1. 程式人生 > >JDK8中JVM對類的初始化探討

JDK8中JVM對類的初始化探討

會有 instr specific strac 遞歸 gets 具體實現 dha 詳情

在《深入理解Java虛擬機》(第二版,周誌明著)中,作者介紹了JVM必須初始化類(或接口)的五種情況,但是是針對JDK7而言的。

那麽,在JDK8中,這幾種情況有沒有變化呢?(我猜測應該會有擴展)

接下來我們探討一下JDK8中JVM類的初始化這一部分內容。

官方文檔為The Java? Virtual Machine Specification, Java SE 8 Edition, 2015-02-13

類的初始化部分在https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.5。

我們先看下《深入理解Java虛擬機》(第二版,周誌明著)中對類初始化的介紹:

技術分享圖片

有且只有五種情況下,當發現相關的類沒有進行過初始化,虛擬機會觸發其初始化:

(1) 調用new, getstatic, putstatic, invokestatic這四條指令時,相關類沒有初始化;

(2) 使用java.lang.reflect包進行反射時,相關類沒有初始化;

(3) 初始化子類時,發現父類沒有初始化;

(4) 主類(包含maini()方法的類)沒有初始化;

(5) JDK7中使用動態語言支持時,如果一個java.lang.invoke.MethodHandle實例正好是對REF_getStatic, REF_putStatic, REF_invokeStatic進行方法句柄解析的結果時;

The Java? Virtual Machine Specification, Java SE 8 Edition中對類或接口進行初始化的內容:

Initialization of a class or interface consists of executing its class or interface initialization method (§2.9).

A class or interface C may be initialized only as a result of:

  • The execution of any one of the Java Virtual Machine instructions new

    , getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic). These instructions reference a class or interface directly or indirectly through either a field reference or a method reference.

    Upon execution of a new instruction, the referenced class is initialized if it has not been initialized already.

    Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.

  • The first invocation of a java.lang.invoke.MethodHandle instance which was the result of method handle resolution (§5.4.3.5) for a method handle of kind 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), or 8 (REF_newInvokeSpecial).

    This implies that the class of a bootstrap method is initialized when the bootstrap method is invoked for an invokedynamic instruction (§invokedynamic), as part of the continuing resolution of the call site specifier.

  • Invocation of certain reflective methods in the class library (§2.12), for example, in class Class or in package java.lang.reflect.

  • If C is a class, the initialization of one of its subclasses.

  • If C is an interface that declares a non-abstract, non-static method, the initialization of a class that implements C directly or indirectly.

  • If C is a class, its designation as the initial class at Java Virtual Machine startup (§5.2).

從這段可以看到大部分和《深入理解Java虛擬機》(第二版,周誌明著)中描述的相同,除了兩點:

(1) 使用動態語言支持時,如果一個java.lang.invoke.MethodHandle 實例是REF_newInvokeSpecial的方法句柄解析結果時,也會觸發類的初始化;

(2) 對於接口而言,如果這個接口申明了一個non-abstract, not-static方法,當實現了這個接口的類初始化時也會觸發這個接口的初始化。

在初始化前,類/接口必須先經過連接階段:驗證,準備,解析(可選)。

Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.

虛擬機在初始化類/接口時,要註意兩個問題:

(1)因為虛擬機是多線程的,要求處理同步問題;

(2)遞歸初始化的問題。

由虛擬機的具體實現來負責處理以上兩個問題。JDK8中使用了一個procedure來完成初始化。

當然這個procedure需要一些條件的滿足,比如相關的Class object必須已經完成了驗證和準備,並且必須是四種狀態中的一種。

詳情可以查看文檔,有空再探討。

JDK8中JVM對類的初始化探討