JVM虚拟机类加载机制(一)
类从被加载到虚拟机内存中开始,到卸载出内存截止,整个生命周期包括:加载、验证、准备、解析,初始化、使用、卸载七个阶段。其中验证、准备、解析三个部分统称为连接。
类初始化情况:
遇到new、getstatic、putstatic 或 invokestatic 这4条字节码指令时,如果没有初始化,则需要触发初始化。生成这4条指令的最常见Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段,以及调用一个类的静态方法时。
使用java.lang.reflect包的方法对类进行发射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
当虚拟机启动时,用户需要制定一个要执行的主类,虚拟机会先初始化这个主类。
以上四种场景成为类的主动引用。除此之外所有引用类的方式都不会触发初始化——被动引用。
第一种情况
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
package main.java.loadclass;
public class SubClass extends SupperClass{
static {
System.out.println("SubClass init!");
}
}
package main.java.loadclass;
public class SupperClass {
static {
System.out.println("supper class");
}
public static int value = 123;
}
package main.java.loadclass;
public class NotInitialization {
public static void main(String[] args){
System.out.println(SubClass.value);
}
}
输出:
supper class
123
第二种情况
package main.java.loadclass;
public class NotInitialization {
public static void main(String[] args){
SupperClass[] sca = new SupperClass[10];
}
}
运行此段代码无输出值,可见SupperClass未初始化。但是虚拟机会自动生成一个同名的类(继承自Object)进行初始化,创建动作由new array触发。
第三种情况
package main.java.loadclass;
public class ConstClass {
static {
System.out.println("ConstClass init!");
}
public static final String HELLOWORLD = "hello world";
}
package main.java.loadclass;
/**
* 常量在编译阶段会存入调用类的常量池中,
* 本质上没有直接引入定义的常量类,
* 因此不会触发定义常量类的初始化。
*/
public class NotInitialization {
public static void main(String[] args){
System.out.println(ConstClass.HELLOWORLD);
}
}
加载
加载过程
通过一个类的全限定名来获取定义此类的二进制字节流。
将这个字节流所带变的静态存储结构转化为方法区的运行时数据结构。
在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这个数据的访问入口。
加载访问方式
从本地系统直接加载
通过网络下载class文件
从zip、jar等归档文件中加载class文件
从原有数据库中提取class文件
将java源文件动态编译为class文件
验证
目的
符合JVM加载字节码符合规范
验证过程
文件格式验证
元数据验证:是否符合java语言规范
字节码验证:确保程序语言合法,符合逻辑
符号引用验证:确保下一步的解析能正常执行。
准备
准备阶段的目的是为被加载的静态变量分配内存,并设置默认初始值,如果是final修饰的常量,初始值为设置的值。
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
对类的字段和方法进行转换
符号引用:代码在编译阶段,虚拟机并不知道具体引用的地址,所以会用符号引用替代
直接引用:在内存中,将符号引用变成具体的引用地址,可以理解成一个指针,偏移量或者句柄
初始化
什么时候初始化?
当虚拟机启动时,初始化用户指定的主类。
使用new该类实例化对象的时候。
读取或设置静态字段的时候,初始化该静态字段的所在的类
调用类静态方法的时候,初始化该静态方法所在的类
使用反射class.forName("xxx")对类进行反射调用的时候,该类需要初始化。
子类的初始化会触发父类的初始化(1、接口除外,父接口在调用的时候才会初始化,2子类引用父类静态字段,只会引发父类的初始化),
如果一个接口定义了default方法,那么直接实现或间接实现接口的类的初始化,会触发该接口的初始化
当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类。
初始化顺序
初始化超类 》执行静态初始化 》类变量初始化
父类的静态变量和静态块赋值
自身的静态变量和静态块赋值
父类的成员变量和块赋值
父类构造器赋值:如果父类中含有有残构造器,则在子类构造器中一定要使用“super(参数)”指定调用父类有参的构造器,不然会报错
自身成员变量和块赋值
自身构造赋值
如何追踪类的加载与卸载:
追踪类的加载与卸载过程
-verbose:class
单独追踪类的加载
-XX:+TraceClassLoading
单独追踪类的卸载
-XX:+TraceClassUnloading

JVM虚拟机类加载机制(一)的更多相关文章
- 深入理解JVM - 虚拟机类加载机制 - 第七章
类加载的时机类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括了:加载/验证/准备/解析/初始化/使用/卸载七个阶段.其中验证/准备和解析统称为连接(Linking). 加载.验证.准 ...
- 【JVM.6】虚拟机类加载机制
一.概述 虚拟机类加载机制:虚拟机把描述类的数据从Class文件中加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型. 与那些在编译时需要进行连接工作的语言不同 ...
- JVM虚拟机—JVM的类加载机制
1 什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...
- 深入理解JVM,虚拟机类加载机制
类加载过程概览 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括以下7个阶段: 加载(Loading) 验证(Verification) 准备(Preparation) 解析(Re ...
- 【JVM】虚拟机类加载机制
什么是类加载 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. <[JVM]类文件结构& ...
- JVM学习笔记-第七章-虚拟机类加载机制
JVM学习笔记-第七章-虚拟机类加载机制 7.1 概述 Java虚拟机描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被 ...
- Java虚拟机类加载机制
看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩 ...
- Java虚拟机类加载机制——案例分析
转载: Java虚拟机类加载机制--案例分析 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...
- Java虚拟机--虚拟机类加载机制
虚拟机类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 类的生命周期如下: 加载 ...
随机推荐
- 使用Truffle 部署智能合约
使用Truffle 部署智能合约 之前我们使用Geth,原生的以太坊Golang工具,分析了创世区块的参数内容,在本地创建了私有以太坊区块链,并使用两个账户进行了挖矿和转账操作,对以太坊有了基本了解. ...
- 如何让 if/else 更优雅?
if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼,有没有什么方法可以让我们避免来写这么多的 if else 呢? 1.使用 return 我 ...
- WebGPU 计算管线、计算着色器(通用计算)入门案例:2D 物理模拟
目录 1. WebGL 2. WebGPU 2.1. 适配器(Adapter)和设备(Device) 2.2. 着色器(Shaders) 2.3. 管线(Pipeline) 2.4. 并行(Paral ...
- 如何理解Node.js和JavaScript的关系
一.Javascript的引擎 浏览器一般有两个引擎,一个是Html引擎,一个是脚本引擎. JavaScript是一种脚本语言,最初用于浏览器的动态显示,方便操作页面数据和内容.但实际上,它也可以在浏 ...
- Maven项目报错:“No goals have been specified for this build”解决办法
clean install scf:run第一种解决办法:找到pom.xml文件,在<build>标签里面添加如下所示的代码即可.<defaultGoal> compile & ...
- 常用的jdbc的Druid连接池配置
spring: datasource: username: root password: 888888 url: jdbc:mysql://localhost:3306/mybatis driver- ...
- 使用Pycharm IDE工具,使用input()函数出现>?符号
Python Console === 如果你是要Pycharm开发Python项目时,出现使用input函数,提示 >? 符号的时候,那应该是开启了Python Console控制台输出,取 ...
- vue Cannot read property ‘tapPromise‘ of undefined
https://blog.csdn.net/qq379682421/article/details/111574290 https://github.com/SimenB/add-asset-html ...
- 面试问题之C++语言:从源文件到可执行文件过程
1.预处理: 预处理过程主要处理那些源文件中的以"#"开始的预编译指令.包括:包含头文件.宏替换.条件编译而不进行语法检查. 2.编译: 编译过程就是把预处理的文件进行一系列的词法 ...
- C# 如何让new 出来的form显示在最外层?
/// <summary> /// 显示比对不同点的位置 /// </summary> public void showDiffImage() { //在此处弹出不一样图 Bi ...