深入理解 JVM——虚拟机类加载机制

类的生命周期是怎样的?

加载->验证->准备->解析->初始化->使用->卸载 (为了支持 Java 语言的运行时绑定 动态绑定,解析可在初始化后完成。)

什么是类加载?

把 .class 文件加载到内存,对其校验,转换,解析,初始化,最终形成可被虚拟机直接使用的 Java 类型的过程。

类加载的具体过程是怎样的?

加载:
通过类的全限定名获取二进制字节流。
将字节流代表的静态存储结构转化成方法区的运行时数据结构。
在内存中生成对应的 Class 对象,作为方法区这个类的各种数据的访问入口。
连接:
验证:确保 Class 文件字节流中的信息符合当前虚拟机的要求,不会危害虚拟机。
1. 文件格式验证:保证输入的字节流可被正确地解析,进入内存的方法区进行存储。
2. 元数据验证:
2.1 是否有父类
2.2 父类是否继承了 final 类
2.3 不符合规范的方法重载,入参一致,返回值不同等。
3. 字节码验证:
3.1 保证跳转指令不会指向方法体以外的字节码指令上等。
4. 符号引用验证:常量池中各类符号引用进行匹配性校验,确保后续的解析动作正常发生。
准备:为类变量分配内存并设置类变量的初始值(譬如 int 类型的赋值为0),类变量进入方法区。
解析:将常量池中的符号引用转化成直接引用的过程,虚拟机规范中尚未规定解析阶段发生的具体时间,可以在加载时对符号引用解析,也可以在符号引用将被使用到前再解析(invokeDynamic)
1. 类或接口的符号引用解析
2. 字段
3. 类方法
4. 接口方法
5. 方法类型
6. 方法句柄
7. 调用点限定符
初始化:真正开始执行类中定义的 Java 程序(字节码),是执行clinit() 方法的过程。该方法由编译器自动收集类中类变量的赋值动作和静态语句块(static{})—— 真正赋值。

什么是类加载器?

类加载阶段中“通过类的全限定名来获取描述此类的二进制字节流”这个动作放到 JVM 外部实现,以便让应用程序自己决定如何获取所需要的类。实现这个动作的代码模块称为“类加载器”。

介绍一下双亲委派机制

分类:启动类加载器<-扩展类加载器<-应用程序类加载器,使用组合而非继承的关系来复用父加载器的代码。
工作过程:一个类加载器收到了类加载的请求,首先不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,因此所有的加载请求最终到了顶层的启动类加载器中,只有当父类反馈无法加载(搜索范围里没有所需的类)时,子加载器才会尝试加载。
好处:Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。无论哪个类要加载A类,最终都是交由启动类加载器去加载。如果没有双亲委派机制,用户编写 java.lang.Object 类并放在 ClassPath 中,由各自的类加载器加载,则 Java 类型体系中最基础的行为也就无法保证了。
ClassLoader.loadClass() 解析:检查是否已加载过,若没有则调用父加载器的 loadClass(),若父类为 null 则默认使用启动类加载器加载。若父加载器加载失败,则抛出 ClassNotFoundException异常后再调用自己的 findClass()进行加载。
破坏双亲委派机制【待完善】:
1. ClassLoader 类 在 jdk1.0就存在,而双亲委派机制在 jdk1.2引入,为了兼容前者。
2. 线程上下文类加载器
2.1 JNDI服务借助线程上下文类加载器去加载所需的 SPI 代码,这是父加载器请求子加载器完成类加载的动作。Java 中涉及到 SPI 的加载:JNDI、JDBC 等。
3. 热部署 OSGI
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值