类的加载连接与初始化过程详解
类型的加载、连接与初始化过程,都是在程序运行期间完成的
加载:最常见为将硬盘的class文件加载到内存中
查找并加载类的二进制数据
连接:将类与类之间的关系确定好并对字节码的处理、验证、校验等,类与类之间的调用等
-验证:确保被加载的类的正确性
-准备:为类的静态变量分配内存,并将其初始化为默认值
-解析:把类中的符号引用转换为直接引用
初始化:静态类型变量的赋值
-为类的静态变量赋予正确的初始值
类加载器:classLoader,每一个类都由他加载到jvm中
java虚拟机结束生命周期:
执行了System.exit()
程序正常执行结束
程序在执行过程中遇到了异常或错误而异常终止
由于操作系统出现错误而导致java虚拟机进程终止
java程序对类的使用方式分为:主动使用、被动使用,所有的java虚拟机实现必须在每个类或接口被java程序“首次主动使用”时才初始化他们。
主动使用:
创建类的实例
访问某个类或接口的静态变量(getstatic),或者对该静态变量赋值(putstatic)
调用类的静态方法(invokestatic)
反射(class.forname("com.test.Test") )
初始化一个类的子类
java虚拟机启动时被标明为启动类的子类(Java Test(包括main方法的类))
jdk 1.7开始提供的动态语言支持 java.lang.invoke.MethodHandle实例的解析结果REF_getStatic等
被动使用都不会导致类的初始化,可能会被加载连接
类的加载指的时将类的 .class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存中创建一个java.lang.Class对象(规范并未说明放在哪里。HotSpot虚拟机放在方法区)用来封装类在方法去内的数据结构
当一个类在初始化时,要求其父类全部都已经被初始化完毕了
对于静态字段来说,只有直接定义了该字段的类才会被初始化
参考:
- https://www.bilibili.com/video/av75247289 推荐这一个,讲的真的好细啊,但是真的好长啊
- 《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第二版》