jvm 类加载的过程, 你学废了吗?

前言

我们在编写完成java代码时, 会把java文件编译成class文件, 然后jvm才能执行, 可是jvm是怎么执行这个过程的呢, 如果你还不清楚是怎样的一个加载过程, 相信你看完这篇博客就学废了。
jvm 类加载的过程, 你学废了吗?

类加载过程

类加载过程大概分为5个阶段: 加载, 验证, 准备, 解析, 初始化
jvm 类加载的过程, 你学废了吗?

加载阶段

这个加载完成了三件事

  • 通过类的全限定类名获取类的二进制流
  • 将字节流中的静态存储结构转化为方法区的运行时数据结构, 就是把一个静态的变量、类信息等存储起来
  • 生成一个java.lang.Class对象, 作为这个类在方法区的访问入口, 这也是反射实现的基础

当然二进制流并非要从哪个class文件中获取, 也可以通过别的途径获取

验证阶段

验证阶段分为 文件格式验证、元数据验证、字节码验证、符号引用验证

  • 文件格式验证
    是否以魔术0xCAFEBABE开头
    主次版本号是否被当前java虚拟机所接受
    常量池中的常量类型是否符合规范
    指向常量的索引是否指向不存在的常量或者不符合类型的常量
    utf-8型的常量中是否有不符合utf-8编码的数据

  • 元数据验证
    这个类是否有父类(除了object类,其他类的父类都是object)
    这个类是否继承了不能够被继承的类
    如果不是抽象类, 是否实现了父类或接口中的要求的方法
    这个类是否与父类中的字段、方法产生矛盾

  • 字节码验证
    保证指令代码的正常运行
    保证不会跳转到方法以外的字节码指令上
    保证类型转换都是正确的

  • 符号验证阶段
    是否可以通过全限定名找到对应的类
    方法字段描述符是否是private、protected、public等的其中一个
    方法中引用的类、字段、方法的可访问性是否可以被当前类所访问

准备阶段

准备阶段的工作很简单, 就是为类中定义的变量分配内存并设置类变量初始值的阶段, 但是要注意, 这里只是为类变量分配了初始值, 而不是实例变量

解析

解析就是把符号引用(与虚拟机的内存布局无关)转为直接引用(与虚拟机的内存布局直接相关)
解析主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用点限定符

  • 对于类或接口是否引用了其他类或者数组等引用类型, 分别用不同的方式去解析, 最后在验证访问权限
  • 对于字段解析确保java虚拟机中字段唯一
  • 方法解析确保方法的权限可访问
  • 接口方法解析确保接口方法的唯一性, 排除二义性

初始化阶段

这个阶段才是真正开始执行类中编写的ava代码, 初始化类变量和其他资源

总结

类加载的过程还是挺复杂的, jvm开发人员想的非常的周到, 确保了虚拟机正常运行不被破坏, 那你学废了吗?