在《深入理解 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 newgetstaticputstatic, 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 getstaticputstatic, 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 方法(实际上就是 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 必须完成了验证和准备,并且必须是四种状态中的一种。

详情可以查看文档,有空再探讨。

JDK 8 - JVM 对类的初始化探讨的更多相关文章

  1. JDK8中JVM对类的初始化探讨

    在<深入理解Java虚拟机>(第二版,周志明著)中,作者介绍了JVM必须初始化类(或接口)的五种情况,但是是针对JDK7而言的. 那么,在JDK8中,这几种情况有没有变化呢?(我猜测应该会 ...

  2. jvm(2)类的初始化(二)和实例化

    深入理解Java对象的创建过程:类的初始化与实例化 对象实例化内存分析: 对内存分配情况分析最常见的示例便是对象实例化: Object obj = new Object(); 这段代码的执行会涉及ja ...

  3. jvm(2)类的初始化(一)

    [深入Java虚拟机]之三:类初始化 类初始化是类加载过程的最后一个阶段,到初始化阶段,才真正开始执行类中的Java程序代码. 1,下面说的初始化主要是类变量的初始化,实例变量的初始化触发条件不同(一 ...

  4. Java技术专区-虚拟机系列-类加载机制(类的初始化)

      类加载的生命周期:  加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载       加载 -> 验证 -> 准备 -& ...

  5. 什么情况下JVM会立即对类进行初始化

    虚拟机规范严格规定了有且只有5种情况必须立即对类进行“初始化”(加载.验证.准备等阶段在此之前开始). 遇到new.getstatic.putstatic.invokestatic等4条字节码指令时. ...

  6. Java虚拟机JVM学习04 类的初始化

    Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...

  7. 关于JVM加载class文件和类的初始化

    关于JVM加载class文件和类的初始化 1.JVM加载Class文件的原理机制 1.1.装载 查找并加载类的二进制数据 1.2.链接 验证:确保被加载类的正确性.(安全性考虑) 准备:为类的静态变量 ...

  8. jvm - 类的初始化过程

    我们知道,我们写的java代码称为源码,想要能够被jvm执行首先需要编译成.class文件,那么编译完到使用又都经理的哪些阶段呢?主要分为以下三个阶段: 加载:查找并加载类的二进制数据(.class文 ...

  9. 实例的初始化由JVM装载类的时候进行,保证了线程的安全性

    在23种设计模式中,单例是最简单的设计模式,但是也是很常用的设计模式.从单例的五种实现方式中我们可以看到程序员对性能的不懈追求.下面我将分析单例的五种实现方式的优缺点,并对其在多线程环境下的性能进行测 ...

随机推荐

  1. numpy模块之创建矩阵、矩阵运算

    本文参考给妹子讲python  https://zhuanlan.zhihu.com/p/34673397 NumPy是Numerical Python的简写,是高性能科学计算和数据分析的基础包,他是 ...

  2. mysqldump 的常用操作

    以下是 mysqldump 的一些使用参数 备份数据库#mysqldump 数据库名 >数据库备份名 #mysqldump -A -u用户名 -p密码 数据库名>数据库备份名 #mysql ...

  3. Python httpServer服务器(初级)

    使用原生的python开发的web服务器,入门级! #!/usr/bin/python # -*- coding: UTF-8 -*- import os #Python的标准库中的os模块包含普遍的 ...

  4. springboot---aop切片编程

    1.介绍 面向切面编程,关注点代码与业务代码分离,就是给指定方法执行前执行后..插入重复代码 关注点:重复代码 切面:被切面的类 切入点:执行目标对象方法,动态植入切片代码 2.部署步骤 2.1:添加 ...

  5. 泛型学习第二天——C#中的List<string>泛型类示例

    在C#代码中使用一系列字符串(strings)并需要为其创建一个列表时,List<string>泛型类是一个用于存储一系列字符串(strings)的极其优秀的解决办法.下面一起有一些Lis ...

  6. HBase协处理器的使用(添加Solr二级索引)

    给HBase添加一二级索引,HBase协处理器结合solr 代码如下 package com.hbase.coprocessor; import java.io.IOException; import ...

  7. keystone DB in devstack

    ~$ mysql -u -p root mysql> use keystone; mysql> show tables;+------------------------+| Tables ...

  8. Nodejs+MongoDB+Bootstrap+esj搭建的个人简易博客

    github:https://github.com/yehuimmd/myNodeBloy Nodejs+MongoDB+jQuery+Bootstrap-esj搭建的个人简易博客 主要功能 前台 : ...

  9. 使用Intellij Idea打开项目不能显示树形目录

    按下列步骤操作:1. 关闭IDEA, 2.然后删除项目文件夹下的.idea文件夹3.重新用IDEA工具打开项目 Open...

  10. 一些蠕虫传播研究的文章——TODO

    www.arocmag.com/getarticle/?aid=4e02d91c19b0cced Internet 蠕虫防范技术研究http://www.arocmag.com/article/100 ...