类加载过程

类的加载、 类加载器子系统

字节码生成(javac 命令,.java->.class),简单编译原理,词法分析、语法分析、语义分析和中间代码生成、优化、目标代码生成

  • 加载

    class二进制流字节码读取进方法区,在内存中生成一个java.lang.Class代表该对象作为访问入口

  • 验证

    • 文件格式验证:是否符合Class文件格式规范、以4字节0xCAFEBABE开头、主次版本是否可以被当前jvm处理、常量池常量类型未被支持等

    • 元数据验证:这个类有无除Object以外的父类、是否继承了不被允许的类(final)、抽象继承是否实现父类所有方法等

    • 字节码验证:对方法体进行校验,不存在危害虚拟机的操作(如指令跳转到方法体外)

      根据数据流和控制流分析语义、逻辑合法

    • 符号引用验证:引用是否能被访问、是否跨权限访问

      重要但非必须,因为验证需要耗费时间,如果开发者确保了没问题,那可以用虚拟机参数-Xverfity:none来关闭验证

  • 准备

    • 在方法区(java8方法区在堆里)为静态变量分配内存并初始化为默认值,不包括实例的初始化。若字段的属性表中存在ConstantValue(同时被static final修饰,单static不是,不会在此阶段赋值)属性,就会在准备阶段直接赋为ConstantValue指定的值,若静态常量没被显示赋值就会报错

    • 为非静态变量赋默认值或空

      注意如int a=2,此阶段会赋值为0,static int b=3,也是0;初始化阶段才开始赋值为2或者3。

  • 解析 (验证准备解析又叫连接)

    • 将常量池内符号引用替换为直接引用的过程。

      符号引用就是一组符号来描述目标,可以是任何字面量;例如person类引用了student类,在编译时jvm是不知道stdent类的实际内存地址的,只能用符号来代替,如CONSTANT_Class_info。

      直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

    • 解析针对接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这7种类符号引用进行。可能会抛出NoSuchMethodError、NoSuchFieldError

  • 初始化

    也就是执行,工作内容包括:

    • 构造方法 或 代码块 或 静态代码块

    • 为类的静态变量赋正确初始值:声明时指定的初始值或静态代码块为其指定的值

    • 若类还没被加载和连接就先加载和连接,父类还没初始化先初始化父类。

      <clinit>:静态变量、静态块,是类级别的初始化。

      <init>:类变量、代码块、构造方法,是实例对象级别的初始化。

      只有类主动使用时才初始化,类主动使用方式:

      1、创建类的实例,也就是new的方式;2、访问某个类或接口的静态变量,或者对该静态变量赋值;3、调用类的静态方法;4、反射(如Class.forName("…"));5、初始化某个类的子类,则其父类也会被初始化;6、Java虚拟机启动时被标明为启动类的类,直接使用java.exe命令来运行某个主类。

  • 使用和卸载

posted @ 2021-04-22 23:35  i%2  阅读(41)  评论(0)    收藏  举报