请选择 进入手机版 | 继续访问电脑版

热点推荐

查看: 78|回复: 1

虚拟机类加载机制

[复制链接]

该用户从未签到

94

主题

94

帖子

282

积分

中级会员

Rank: 3Rank: 3

积分
282
发表于 2020-2-19 14:22:49 | 显示全部楼层 |阅读模式
    虚拟机类加载机制就是虚拟机把描述类信息的数据从Class文件中加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的过程。
   Class文件最终都需要加载到虚拟机后才能被运行和使用,而虚拟机如何加载这些Class文件,Class文件中的信息进入到虚拟机后会有什么变化呢?这也是下面要讲解的内容。
一、类加载的时机

一个类型从被加载到卸载出内存,它的整个生命周期将经历以下七个阶段(验证、准备、连接又被合称为连接):
     加载、验证、准备、初始化、卸载这五个阶段的顺序是确定的,类型的加载过程必须按照这个顺序按部就班的开始,而解析阶段就不一定:它在某些情况下可以放在初始化阶段之后开始,这是因为Java语言的运行时绑定特性(动态绑定)。注意,这里写的是 “ 开始 ”而不是 “ 进行 ”,强调这点是因为这些阶段通常都是交叉的混合进行,会在一个阶段执行过程中调用、激活另一个阶段。
关于在什么情况下需要开始类加载过程的第一阶段 “ 加载 ”,《Java虚拟机规范》中没有进行强制要求,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,《Java虚拟机规范》则是严格规定了有且只有6中情况必须立即对类进行 “ 初始化 ”。
1. 遇到new(new指令实例化对象)、getstatic(读取一个类型的静态字段)、 putstatic(调用一个类的静态方法)、 invokestatic这四条指令,如果没有进行初始化,则需要先触发其初始化。
2. 使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有初始化,则触发其初始化。
3.  当初始化一个类,发现其父类还没有初始化的时候。
4.  当虚拟机启动时候,用户指定的main方法所在的类。
5.  JDK 8接口中的默认方法,如果这个接口的实现类进行初始化,那么接口的初始化要发生在其之前 。
6.  JDK7 动态语言支持时,如果一个实例被解析为REF_getStatic、REF_putStatic等等,这个方法句柄对应的类没有初始化的时候需要先初始化。
除此之外其他的引用类型的方式都不会触发初始化,称之为被动引用。
被动引用案例:
   上面代码通过子类Son调用父类的静态字段value,控制台窗口只用 “父类初始化”并没有 “子类类初始化”,这就说明子类调用父类的静态字段并不会触发子类的初始化。


    上面的案例验证了通过数组定义来引用一个类,并不会触发引用类的初始化阶段。虽然这里没有触发Father类的初始化阶段,但这里却触发了一个名为 “[LTest.Farher”的类的初始化,这是一个由虚拟机自动生成的、直接继承于java.lang.Object的子类,创建动作由字节码指令newarray触发。


    可以看出上述代码运行后,并没有输出 “父类初始化”,这是因为虽然Java源码中确实引用了Father类的常量value,但是其实在编译阶段通过常量传播优化,已经将此常量值“123”,存入了ExtendTest类的常量池中,以后ExtendTest对于常量Father.value的引用,实际上都转变成了ExtendTest对于自己常量池的引用了。
接口的加载过程与类的加载过程稍有不同:真正的区别在于上面说的主动触发初始化场景中的第三点,在一个接口初始化的时候,并不要求其所用的父接口都完成初始化,只有在真正使用到父接口的时候才会初始化父接口。
二、类加载的过程

1、加载

Java吧 收集整理 java8论坛 www.java8.com
回复

使用道具 举报

该用户从未签到

2

主题

9

帖子

20

积分

新手上路

Rank: 1

积分
20
发表于 6 天前 | 显示全部楼层
这么强,支持楼主,佩服
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表