类加载过程中每个步骤的顺序

我们已经知道,类加载的过程包括:加载、连接、初始化,连接又分为:验证、准备、解析,所以说类加载一共分为5步:加载、验证、准备、解析、初始化。

其中加载、验证、准备、初始化的开始顺序是依次进行的,这些步骤开始之后的过程可能会有重叠。 
而解析过程会发生在初始化过程中。

类加载过程中“初始化”开始的时机

JVM规范中只定义了类加载过程中初始化过程开始的时机,加载、连接过程都应该在初始化之前开始(解析除外),这些过程具体在何时开始,JVM规范并没有定义,不同的虚拟机可以根据具体的需求自定义。

初始化开始的时机:

  • 在运行过程中遇到如下字节码指令时,如果类尚未初始化,那就要进行初始化:new、getstatic、putstatic、invokestatic。这四个指令对应的Java代码场景是:

    •   通过new创建对象;
    •   读取、设置一个类的静态成员变量(不包括final修饰的静态变量);
    •   调用一个类的静态成员函数。
  • 使用java.lang.reflect进行反射调用的时候,如果类没有初始化,那就需要初始化;
  • 当初始化一个类的时候,若其父类尚未初始化,那就先要让其父类初始化,然后再初始化本类;
  • 当虚拟机启动时,虚拟机会首先初始化带有main方法的类,即主类;

主动引用 与 被动引用

JVM规范中要求在程序运行过程中,“当且仅当”出现上述4个条件之一的情况才会初始化一个类。如果间接满足上述初始化条件是不会初始化类的。 
其中,直接满足上述初始化条件的情况叫做主动引用;间接满足上述初始化过程的情况叫做被动引用。 
那么,只有当程序在运行过程中满足主动引用的时候才会初始化一个类,若满足被动引用就不会初始化一个类。

接口的初始化

接口和类都需要初始化,接口和类的初始化过程基本一样,不同点在于:类初始化时,如果发现父类尚未被初始化,则先要初始化父类,然后再初始化自己;但接口初始化时,并不要求父接口已经全部初始化,只有程序在运行过程中用到当父接口中的东西时才初始化父接口(没用到父接口的变量或者方法时不需要初始化父接口)。

例子

被动引用的场景示例

public class Fu{
public static String name = "test";
static{
System.out.println("父类被初始化!");
}
}
public class Zi{
static{
System.out.println("子类被初始化!");
}
}
public static void main(String[] args){
System.out.println(Zi.name);
}
输出结果:
父类被初始化!
test
原因分析:
本示例看似满足初始化时机的第一条:当要获取某一个类的静态成员变量的时候如果该类尚未初始化,则对该类进行初始化。
但由于这个静态成员变量属于Fu类,Zi类只是间接调用Fu类中的静态成员变量,因此Zi类调用name属性属于间接引用,
而Fu类调用name属性属于直接引用,由于JVM只初始化直接引用的类,因此只有Fu类被初始化。
public class A{
public static void main(String[] args){
Fu[] arr = new Fu[10];
}
}
输出结果:
并没有输出“父类被初始化!”
原因分析:
这个过程看似满足初始化时机的第一条:遇到new创建对象时若类没被初始化,则初始化该类。
但现在通过new要创建的是一个数组对象,而非Fu类对象,因此也属于间接引用,不会初始化Fu类。
public class Fu{
public static final String name = "test";
static{
System.out.println("父类被初始化!");
}
}
public class A{
public static void main(String[] args){
System.out.println(Fu.name);
}
}
输出结果:
test
原因分析:
本示例看似满足类初始化时机的第一个条件:获取一个类静态成员变量的时候若类尚未初始化则初始化类。
但是,Fu类的静态成员变量被final修饰,它已经是一个常量。
被final修饰的常量在Java代码编译的过程中就会被放入它被引用的class文件的常量池中(这里是A的常量池)。
所以程序在运行期间如果需要调用这个常量,直接去当前类的常量池中取,而不需要初始化这个类。

JVM的类加载时机的更多相关文章

  1. 【JVM】类加载时机与过程

    虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制.下面来总结梳理类加载的五个阶段. 类加载发生在 ...

  2. 从一道面试题来认识java类加载时机与过程

    说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要的内容. 1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可 ...

  3. java类加载时机与过程

    转自:http://www.tuicool.com/articles/QZnENv 说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要 ...

  4. 深入理解JVM(3)——类加载机制

    1.类加载时机 类的整个生命周期包括了:加载( Loading ).验证( Verification ).准备( Preparation ).解析( Resolution ).初始化( Initial ...

  5. 从一道面试题来认识java类加载时机与过程【转】

    说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要的内容. 1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可 ...

  6. JVM自定义类加载器加载指定classPath下的所有class及jar

    一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...

  7. 漫谈JVM之类加载机制(篇一)

    前言 最近在看一本书,发现代码里用到了Thread.currentThread().getContextClassLoader(),为什么类加载器还与线程有关系呢,为什么不直接使用ClassLoade ...

  8. 深入理解JVM之类加载

    ---title: [学习]深入理解JVM之类加载.mddate: 2019-10-20 22:20:06tags: JVM 类加载--- Java类的加载,连接,初始化都是在程序运行期间执行的 ## ...

  9. JVM:类加载与字节码技术-2

    JVM:类加载与字节码技术-2 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 内容 这部分内容在上一篇笔记中: 类文件结构 字节码指令 编译期处理 类加载阶段 ...

随机推荐

  1. 原创:MVC 5 实例教程(MvcMovieStore 新概念版:mvc5.0,EF6.01) - 4、创建数据上下文和数据实体模型

    说明:MvcMovieStore项目已经发布上线,想了解最新版本功能请登录 MVC影视(MvcMovie.cn) 进行查阅.如需转载,请注明出处:http://www.cnblogs.com/Dodu ...

  2. 在TFS 2013的迭代视图中修改工作项数目限制

    当TFS迭代中的工作项数目超过500时,在TFS的网页(Web Access)显示中就会出现红色警告提示"积压工作(backlog)中的项数超出配置的限制500.当前总数为529-.&quo ...

  3. UDP实现一个简易的聊天室 (Unity&&C#完成)

    效果展示(尚未完善) UDP User Data Protocol 用户数据报协议 概述 UDP是不连接的数据报模式.即传输数据之前源端和终端不建立连接.使用尽最大努力交付原则,即不保证可靠交付. 数 ...

  4. JS 浏览器对象

    1.window对象 1.1 window对象 window对象是BOM的核心.window对象指当前的浏览器窗口 所有JavaScript全局对象 .函数以及变量均自动成为window对象的成员 全 ...

  5. Hibernate继承映射(@Inheritance)

    继承映射在 Annotation 中使用 @Inheritance 注解,并且需要使用 strategy 属性指定继承策略,继承策略有 SINGLE_TABLE.TABLE_PER_CLASS 和 J ...

  6. iOS 禁止多按钮同时响应

    只需要对相应的按钮添加一行代码 [aButton setExclusiveTouch:YES];

  7. WordPress插件Social Warfare<=3.5.2 无需登录RCE漏洞

    该漏洞只存在于Social Warfare插进的3.5.0.3.5.1和3.5.2版本中,其他版本不存在. 2019年3月21日插件作者紧急发布了3.5.3版本以修复高危的RCE漏洞,在<=3. ...

  8. springmvc执行流程 源码分析

    进入DispatcherServlet 执行onRefresh,然后执行初始化方法initStrategies.然后调用doService——>doDispatch. 根据继承关系执行Servl ...

  9. 【Oracle 12c】CUUG OCP认证071考试原题解析(35)

    35.choose the best answer View the Exhibit and examine the description of the EMPLOYEES table. Evalu ...

  10. spring-mybatis源码追踪

    启用一个扫描类 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <propert ...