JVM学习笔记-类加载和类加载器

JVM学习笔记-类加载和类加载器

一、类加载流程

这张图是从.java文件到执行的过程,我们主要看类加载这一部分
file

1.1 加载

查找并加载类文件的二进制数据

1.2 连接

就是讲已经读入内存的类的二进制数据合并到JVM运行时的环境中去,包含如下步骤:

1.2.1验证:

确保被夹在类的正确性
类连接主要验证的内容:(可以学完类加载器和双亲委派后再来理解)
(1)类文件结构检查:按照JVM规范规定的类文件结构进行
(2)元数据验证:对字节码描述的信息(如该类是否继承了不允许继承的类(被final修饰的类)、是否包含父类等)进行语义分析,保证其符合Java语言规范要求
(3)字节码验证:通过对数据流(方法体)和控制流(如if else 等语句)进行分析,确保程序语义是合法并且符合逻辑的。字节码验证主要对方法体进行校验
(4)符号引用验证:对类自身以外的信息,也就是常量池中的各种符号引用,进行匹配校验

1.2.2 准备:

为类的静态变量分配内存(在初始化前,仅仅分配了内存),并初始化它们(准备初始化)

1.2.3 解析:

(1)解析的过程,就是把常量池中的符号引用转换成直接引用的过程
☆符号引用:以一组无歧义的符号来描述所引用的目标,与虚拟机的实现无关
☆直接引用:直接指向目标的指针,相对偏移量,或者是能间接定位到目标的句柄,是和虚拟机实现相关的(硬件平台不同,虚拟机的实现可能不同)

(2)解析主要针对:类、接口、字段、类方法、接口方法、方法类型、(方法句柄、调用点限定符【这两个点还不太清晰】)

类连接中的解析

1.3 初始化

为类的静态变量赋初始值

二、类加载要完成的功能

(1)通过类的全限定名来获取该类的二进制字节流
(2)把二进制字节流转化为方法区的运行时数据结构
(3)在上创建一个java.lang.Class对象,用来封装类在方法区内的数据结构

三、加载类的方式

(1)最常见的方式:本地文件系统中加载,从jar等归档文件中加载
(2)动态的方式:将java源文件动态编译成class
(3)其他方式:网络下载、从转悠数据库中加载等等

四、类加载器(这里我详解的是JDK8,更高版本的有所迭代)

请参见我的另一篇文章:
附加内容:
(1)java程序不能直接引用启动类加载器,而是直接默认就使用启动类加载器
(2)类加载器并不需要等到某个类“首次主动使用”的时候才加载它,JVM规范允许类加载器在预料到某个类将要被使用的时候就预先加载它
(3)如果在加载的时候.class文件缺失,会在该类首次主动使用的时候报错(LinkageError错误),如果一直没有被使用,就不会报错

五、双亲委派模型(这里我详解的是JDK8,更高版本的有所迭代)

请参见我的另一篇文章:
附加内容:
(1)每个类加载器都有自己的命名空间,命名空间由 该加载器以及所有它的父加载器所加载的类构成,不同的命名空间,可以出现类的全路径名相同的情况。(命名空间可以通俗的理解为一个程序(有这些类组成)可以多开,每次开启的程序就属于不同的命名空间)

六、类的初始化

类的初始化就是为类的静态变量赋初始值,或者说是执行类构造器方法的过程
(1)如果类还没有加载和连接,就先加载和连接
(2)如果类存在父类,且父类没有初始化,就先初始化父类
(3)如果类中存在初始化语句,就依次执行这些初始化语句
(4)如果是接口的话:{
a、初始化一个类的时候,并不会先初始化它实现的接口
b、初始化一个接口时,并不会初始化它的父接口
c、只有当程序首次使用接口里的变量或者是调用接口方法的时候,才会导致接口初始化
}
(5)调用CLassloader类的loadClass方法来装载一个类,并不会初始化这个类,因为不是对类的主动使用

六、类的初始化

版权声明:
作者:十下
链接:http://blog.edkso.cn/?p=922
来源:十下博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>