类加载深入解析

在Java代码中,类型(Class、Interface、Enum,类型绝大多数是提前编写好的,但是也有些是在运行期动态的生成出来如动态代理)的加载、连接、初始化过程都是在程序运行期间(提供了更大的灵活性,增加了更多的可能性)完成的

Java虚拟机与程序的生命周期,在如下几种情况下,Java虚拟机将结束生命周期

  • 执行了System.exit()方法
  • 程序正常执行结束
  • 程序在执行过程中遇到异常或错误而异常终止
  • 由于操作系统出现错误而导致Java虚拟机进程终止

1 类的加载

  类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存中创建一个java.lang.Class对象(规范并未说明Class对象位于哪里,HotSpot虚拟机将其放在了方法区中)用来封装类在方法区内的数据结构

  • 加载.class文件的方式
    • 从本地系统中直接加载
    • 通过网络下载.class文件
    • 从zip,jar等归档文件中加载.class文件
    • 从专有数据库中提取.class文件
    • 将Java源文件动态编译为.class文件

2 类的连接

  • 验证:确保被加载的类的正确性
  • 准备:为类的静态变量分配内存,设置默认值,但是到达初始化之前,类的静态变量都没有初始化为真正的初始值
  • 解析:解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用转换为直接引用的过程

3 类的初始化

  为类的静态变量赋予正确的初始值

4 类的使用

  • Java程序对类的使用方式可分为两种
    • 主动使用:所有的Java虚拟机实现必须在类或者接口被Java程序“首次主动使用”时才初始化它们
      • 创建类的实例
        • 为新的对象分配内存
        • 为实例变量赋默认值
        • 为实例变量赋正确的初始值
        • java编译器为它编译的每一个类都至少生成一个实例初始化方法,在java的class文件中,这个实例初始化方法被称为“<init>”,针对源代码中每一个类的构造方法,java编译器都产生一个<init>方法
      • 访问某个类或接口的静态变量(在使用静态字段的时候,对于静态字段来说,只有直接定义了该字段的类才会被初始化)或者对该静态变量进行赋值
      • 调用类的静态方法
      • 反射:如Class.forName("com.jqbai.Test")
      • 初始化一个类的子类(当一个类在初始化时,要求其父类全部都已经初始化完毕了)
      • Java虚拟机启动时被标明为启动类的类(Java Test)
      • JDK1.7开始提供动态语言支持:java.lang.invoke.MethodHandle实例的解析结果REF_getStatic,REF_putStatic,REF_invokeStatic句柄对应的类没有初始化,则初始化
    • 被动使用
      • 除了上述主动使用,其它使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化,如:数组Test[] tests = new Test[1]

5 类的卸载 

  类卸载之后就不能创建对象了,需要重新加载才可以创建对象

posted @ 2018-12-27 09:12  jqbai  阅读(428)  评论(0编辑  收藏  举报