JDK8中JVM对类的初始化探讨
Posted Trace Spaces
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK8中JVM对类的初始化探讨相关的知识,希望对你有一定的参考价值。
在《深入理解 Java 虚拟机》(第二版,周志明著)中,作者介绍了 JVM 必须初始化类(或接口)的五种情况,但是是针对 JDK 7 而言的。
那么,在 JDK 8 中,这几种情况有没有变化呢?(我猜测应该会有扩展)
接下来我们探讨一下 JDK 8 中 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) 主类(包含 main()方法的类)没有初始化;
(5) JDK 7 中使用动态语言支持时,如果一个 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 packagejava.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 方法(实际上就是 JDK 8 新增的 default method),当实现了这个接口的类初始化时也会触发这个接口的初始化。
在初始化前,类/接口必须先经过连接阶段:验证,准备,解析(可选)。
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
虚拟机在初始化类/接口时,要注意两个问题:
(1)因为虚拟机是多线程的,要求处理同步问题;
(2)递归初始化的问题。
由虚拟机的具体实现来处理以上两个问题。JDK 8 中使用了一个 procedure 来完成初始化。
当然这个 procedure 需要满足一些条件:比如相关的 Class object 必须完成了验证和准备,并且必须是四种状态中的一种。
详情可以查看文档,有空再探讨。
以上是关于JDK8中JVM对类的初始化探讨的主要内容,如果未能解决你的问题,请参考以下文章