1. 加载.class文件的方式

  • 1)从本地系统中直接加载

  • 2)通过网络下载.class文件

    典型场景:Web Applet (小程序应用)

  • 3)从zip,jar等归档文件中加载.class文件

    典型场景:后续演变为jar/war格式

  • 4)从专有数据中提取.class文件

    典型场景:JSP应用从专有数据库中提取.class文件, 比较少见

  • 5)将Java文件动态编译为.class文件,运行时计算而成

    典型场景:动态代理

  • 6)将Java文件动态编译为.class文件,运行时计算而成

    典型场景:动态代理

  • 7)从加密文件中获取

    典型场景:典型的防Class文件被反编译的保护措施

2. 类加载流程

装载 -> 链接(验证、准备、解析) -> 初始化

所谓的类加载机制就是:
虚拟机把Class文件加载到内存
并对数据进行校验,转换解析和初始化
形成虚拟机可以直接使用的Java类型,即java.lang.Class

2.1 装载(Load)

查找和导入.class文件
1)通过一个类的全限定名获取定义此类的二进制字节流
2) 将字节流所代表的静态存储结构转化为方法区的运行时的数据结构
3) 在Java堆中生成一个代表这个类的java.lang.Class对象,作为这些数据在方法区中的访问入口

此时运行时数据区有哪些数据:

  • 方法区: 类信息、静态变量、常量
  • 堆:代表被加载类的java.lang.Class对象
2.2.1 验证(Verify)
  • 文件格式

    a. 是否以16进制CAFEBABY开头
    b. 版本号是否正确

  • 元数据验证(Java语法校验)

    a. 是否有父类
    b. 是否继承了final类
    c. 非抽象类是否实现了所有抽象方法

  • 字节码验证

    a. 运行检查
    b. 栈数据类型和操作码操作参数是否吻合
    c. 跳转指令执行合理的位置

  • 符号引用验证

    a. 常量池中描述类是否存在
    b. 访问的方法或者字段是否存在 且 具有足够的权限

2.2.2 准备(Prepare)

为类的静态变量分配内存,并将其初始化为默认值

这里不包含final 修改的static, 因为final在编译时就会分配

2.2.3 解析(Resolve)

把类中的符号引用转为直接引用

2.3 初始化(Initailize)

初始化阶段是执行类构造器Class.init()方法的过程。