Java虚拟机二三事:虚拟机类加载机制

本文详细介绍了Java虚拟机的类加载机制,包括加载、验证、准备、解析和初始化五个阶段。加载阶段涉及类的二进制字节流获取,验证确保字节流的合法性,准备阶段为类变量分配内存并赋予默认值,解析阶段将符号引用转为直接引用,初始化则执行cinit方法。类加载器在其中起关键作用,遵循双亲委派模型,保证类加载的有序性和安全性。
摘要由CSDN通过智能技术生成

概述

虚拟机把Class文件加载到内存,经过校验、解析和初始化,最终转换成虚拟机可以使用的Java类型,这就是Java的虚拟机类加载机制。
总体流程如图
在这里插入图片描述

一、加载

触发加载的时机

如果类没有初始化,那么以下几种方式会触发类的加载

  • 当调用以下字节码指令
    • 使用new初始化对象
    • 访问类的static变量、static方法
  • 反射访问类
  • 触发了子类的初始化,先从父类开始初始化
  • 虚拟机启动时需要执行的主类,也就是包含main函数的类
  • 使用MethodHandler

这里有两个注意的点

  1. 通过数组定义来使用类,不会触发类的加载
  2. 尽量把固定的int值定位staic final常量,也不会触发类的加载(这是因为在编译阶段,对static final常量进行了优化,都放在常量池中,所以实际上触发的是对常量池的调用)
SubClass[] classArray = new SubClass[10];

public static final String value = "SubClass value";

还有一点,子接口的初始化不会影响父接口,只有用到父接口,比如父接口中定义的常量,才会触发父接口的初始化

加载

通过类的全限定名获取这个类的二进制字节流,在内存中生成代表这个类的class对象

  • 加载阶段可以用系统的类加载器,也可以用自定义的类加载器
  • 数组不通过类加载创建,而是虚拟机直接创建,但是数组的元素类型最终还是要通过类加载器去加载

二、验证

验证class字节流是否合法。
因为class字节流不一定是java源码编译而来,所以虚拟机需要保证class合法的,不会对载入了错误的字节流导致崩溃

  • 文件格式验证:文件头是否合法
  • 元数据验证:是否有父类,是否父类是不允许被继承的
  • 字节码验证:语义合法
  • 符号引用验证:当要把符号引用转换为直接饮用的时候,通过类中的权限定名是否能找到对应的类

三、准备

为类变量准备内存。
设置static变量的初始值,但跟真正的初始化有区别,此处只是赋一个默认值

public static int value = 123;

比如这种,会赋0。但是如果是这种,就会直接赋值

public static final int value = 123;

四、解析

将符号引用转换为直接引用。
符号引用:一组用来描述目标的符号,只要使用时能定位到目标即可
直接引用:直接指向目标的指针或句柄
解析内容

  • 类或接口的解析
  • 类或接口的字段、方法解析

五、初始化

调用cinit方法,进行变量的初始化。
cinit方法是编译器收集的所有变量赋值操作和static代码块合并而成,顺序是按源文件中的顺序决定的

  • 先执行父类的cinit,然后在执行子类的
  • 这就意味着父类是static代码块优于子类执行

虚拟机会保证多线程环境下的cinit方法的执行,多个线程访问,只有一个线程可以调用cinit方法,这就是内部类实现单例的原理

类加载器

使用与卸载就不多说了,当虚拟机发现没有对该类型的引用的时候,会触发类的卸载
什么是类加载器?通过一个类的全限定名来获取这个类的二进制流,放到java虚拟机外部去实现,以便让应用程序自己决定如何去加载这个类

类与类加载器

比较两个类是否相等,只有判断两个类,只有判断在同一个类加载器下才有意义,即使是同一个class对象,用不同的类加载器加载,那么这个类 必不相等

双亲委派模型

在这里插入图片描述
启动类加载器:JAVA_HOME\lib类库加载到虚拟机内存中
扩展类加载器:JAVA_HOME\lib\ext 目录中
应用程序类加载器:系统类加载器,加载用户类路径上所制定的类库。默认类加载器

  1. 如果一个类加载器收到了加载类的请求,都是先交给父类加载,每一层都是如此
  2. 只有父加载器反馈无法加载,子类加载器才会尝试加载
    这样的好处是,有优先级的层次关系,比如object,哪个类加载器都要加载,最终委派给顶层

破坏双亲委派模型

重写loadclass方法,特殊的类自己处理,其他的调用super方法

参考

《深入理解JAVA虚拟机》

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值