bilibili-深入理解JVM 虚拟机 学习笔记
p9 _类加载器深入解析及重要特性剖析(9)
- 加载
- 把二级制形式的 java 类型读入到 jvm 中
- 连接
- 验证
- 准备
- 为类变量分配内存,设置默认值
- 解析
- 在类型的常量池中寻找 类、接口、字段和方法的符号引用,并把这些符号引用替换成直接引用;
- 初始化
- 为类变量赋予编程工程师设置的初始值,替换 jvm 设置的默认值;
- 类的实例化
- 为新对象分配内存
- 为实例对象赋予 jvm 设置的默认初始值
- 为实例对象赋予 编程工程师 设置的初始值
- java 编译器 编译的每一个类都至少生成一个实例初始化方法,在 java 的 class 文件中,这个实例的初始化方法被称为
<init>
;
针对源代码中的每个类的构造方法,java 编译器都产生一个方法;
- 垃圾回收和对象终结
- 类的加载的最终产物是
位于内存中的 Class 对象
; Class 对象封装了类在方法区内的数据结构
,并向 Java 程序员提供了访问方法区内的数据结构的接口;- 类加载器(两种类型)
- Java 虚拟机自带的类加载器
- 根类加载器(启动类加载器) BootstrapClassLoader
- 扩展类加载器 ExtensionClassLoader
- com.sun.org.apache.xalan.internal.XalanConstants#JDK_EXTENSION_CLASSLOADER
- 系统(应用)类加载器 SystemClassLoader
- ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
- 用户自定义的类加载器
- java.lang.ClassLoader 的子类
- public abstract class ClassLoader
- 定制类的加载方式
- java.lang.ClassLoader 的子类
- Java 虚拟机自带的类加载器
- 类加载器
并不需要
等到某个类被首次主动使用
时再加载它- JVM 规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载过程中遇到了 .class 文件缺失或存在错误,类加载器会在程序
首次主动使用
该类时报告错误( java.lang.LinkageError );如果该类一直没有被程序主动使用,那么类加载器就不会报告错误
;
- JVM 规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载过程中遇到了 .class 文件缺失或存在错误,类加载器会在程序
- 类被加载后,就进入到连接阶段;
连接
就是将已经读入到内存中的类的二进制数据合并到虚拟机的运行时环境
中。- 类的验证的内容
- 类文件的结构检查
- 语义检查
- 字节码检查
- 二进制兼容性检查
- 等等
- 准备阶段
- 为类变量分配内存
- 设置默认值
- 解析阶段
- 为类变量赋予初始值
- 声明时初始化
- 静态代码块中初始化
- 为类变量赋予初始值
- 类的验证的内容
- 初始化阶段
- 静态变量的声明,以及静态代码块都被看做
类的初始化语句
; - 类的初始化步骤
- 假如这个类还没有被加载和连接,那么先进行加载和连接;
- 假如该类存在直接父类,并且直接父类还没有被初始化,那么先初始化直接父类(针对所有父类,但不包括接口);
- 假如类中存在
初始化语句
(静态变量声明,静态代码块),那么按书写顺序依次执行
这些初始化语句;
- 类的初始化时机(主动使用时)
- 创建类实例( new Object() )
- 初始化该类的子类
- get or set 静态变量
- 访问静态方法
- 反射 Class.forName()
- jvm 启动类(public static void main 方法所在类)
- 动态语言支持:MethodHandle 实例的解析结果 REF_getStatic 句柄对应的类没有初始化时则进行初始化;
- 还包括 REF_putStatic 句柄
- REF_invokeStatic 句柄
- 除了上诉方式,其他使用 Java 类的方式被看做 被动使用,不会导致类的初始化;
- 调用 ClassLoader 类的
loadlass 方法
加载一个类,并不是对一个类的主动使用,并不会导致类的初始化; - 双亲委派
- 类加载器
- 所有用户自定义的类加载器都应该继承 java.lang.ClassLoader
- 静态变量的声明,以及静态代码块都被看做
P10 _初始化对于类与接口的异同点深入解析(10)
package new_package.jvm.p10;
public class MyTest5 {
public static void main(String[] args) {
System.out.println(MyChild5.a);
}
}
interface MyParent5 {
public static int a = 6;
public static final Thread thread = new Thread() {
{
System.out.println("Hello MyParent5");
}
};
}
interface MyChild5 extends MyParent5 {
// 注意:接口中的参数,默认为 public static final
public static int b = 12;
}
// 6
当一个类初始化,它实现的接口并不会被初始化;
package new_package.jvm.p10;
public class MyTest5 {
public static void main(String[] args) {
System.out.println(MyChild5.a);
}
}
class MyParent5 {
public static int a = 6;
public static final Thread thread = new Thread() {
{
System.out.println("Hello MyParent5");
}
};
}
class MyChild5 extends MyParent5 {
// 注意:接口中的参数,默认为 public static final
public static int b = 12;
}
// Hello MyParent5
// 6