类的加载过程

  • 加载 Loading
    • 通过一个类的全限定名获取定义此类的二进制字节流
      • 加载方式
        • 从本地系统中直接获取
        • 通过网络获取,web applet
        • 从zip压缩包中获取,拓展到jar和war等
        • 运行时计算生成,典型是动态代理
        • 由其他文件生成,常见jsp
        • 数据库中提取class,很少用,数据库中存放二进制
        • 加密文件中,解密获的class,比如防范编译措施等
          • 这里需要自定义类加载器,先进行解
    • 将这个字节流所代表的静态结构转化为方法区(落地实现,jdk7之前包括7叫永久代,jdk7之后叫元数据)的运行时数据结构
    • 在内存中生成一个代表这个类的java.lang.class的对象,作为方法区中这个类的各种数据的访问入口。
  • 连接 Linking
    • 验证 verify
      • 目前在于确保class文件自己留中包含信息符合当前虚拟机要求,保证加载的正确性,不会危害虚拟机自身安全
      • 主要包括四种验证
        • 文件格式验证
          • 主要验证字节流是否符合Class文件格式规范,并且能被当前的虚拟机加载处理。
        • 元数据验证
          • 对字节码描述的信息进行语义的分析,分析是否符合java的语言语法的规范。
        • 字节码验证
          • 最重要的验证环节,分析数据流和控制,确定语义是合法的,符合逻辑的。主要的针对元数据验证后对方法体的验证。保证类方法在运行时不会有危害出现。
        • 符号引用验证
          • 主要是针对符号引用转换为直接引用的时候,是会延伸到第三解析阶段,主要去确定访问类型等涉及到引用的情况,主要是要保证引用一定会被访问到,不会出现类等无法访问的问题。
    • 准备 prepare
      • 为变量内分配内存,并设置该类型默认初始值。
      • 这里不包含final修饰的static,因为final在编译的时候就会分配了,准备阶段会显示初始化。
      • 这里部分给实例变量分配内存和初始化,类变量会分配在方法区中,而实例变量会随着对象一起分配到java堆中。
    • 解析 resolve
      • 将常量池中的符号引用转换为直接引用的过程。
      • 事实上,解析操作往往会伴随着jvm完成初始化之后在执行
      • 符号引用就是一组符号来描述所引用的目标,符号引用字面量形式明确定义在《java虚拟机规范》的class文件格式中,直接引用就是直接指向目标的指针、相对偏移量或间接定位到目标的句柄。
      • 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等,对应常量池中的CONSTAT_class_info、CONSTAT_fielderf_info、CONSTAT_methodref_info
  • 初始化 initial
    • 初始化过程就是执行类构造器方法()的过程
    • ()方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
    • 构造器方法中指令按语句在源文件中出现顺序执行。
    • ()不同于类构造器,构造器是虚拟机视角下的()
    • 若有父类,jvm会保证子类的()执行前,父类的()已执行完毕。
    • 虚拟机保证一个类的()方法在多线程下同步锁。