Java虚拟机之类的生命周期

    Java作为一种面向对象语言,类是其非常重要的组成部分。Java程序经过编译之后,每个类或接口都会对应一个class文件。Java类型的生命周期就是指一个类型的class文件从被JVM加载到被JVM卸载的全过程。类型的生命周期一般包括装载、连接、初始化、使用和卸载五个阶段。

1.装载

    在装载阶段,Java虚拟机类加载器把类信息从二进制class文件读入JVM的方法区中,并在堆中创建该类型的java.lang.Class类的实例。
    在class文件中,类型的信息是以一定格式组织的二进制数据流。而在虚拟机中,类型的信息是以一定内部数据结构形式存储在方法区中,同时每个类在堆中都有一个java.lang.Class类的实例,这个类的实例可以找到该类型在方法区中的类型数据。
    类型需要通过类装载器进行装载,有两种类装载器:启动类装载器和自定义类装载器。启动类装载器是Java虚拟机的一部分,而自定义类装载器是用户自己定义的java.lang.ClassLoader的子类。每个类装载器都有一个命名空间,用来管理自己装载的类。不同的类装载器之间不会相互干扰,从而有助于安全的实现。

2.连接

    装载阶段只是将类型的信息读入到虚拟机中,但是这些类型数据之间都是独立的,还不能真正被使用。连接阶段将方法区中的类型数据转化为虚拟机运行时的状态,即将这些类型数据关联起来,并为它们准备运行时所需要的资源。
    连接阶段可以细分为三个步骤:验证、准备和解析。
  • 验证:确认类型信息符合Java语言规范,保证它不会危及虚拟机的完整性。
    验证内容主要包括:
    1. 类型与超类型之间不存在不兼容
    2. final类不能有子类
    3. final方法不能被覆盖
    4. 除Object类外的所有类都必须有一个超类 
  • 准备:为类变量非常内存,并设置默认初始值。
  • 解析:将类型的常量池中符号引用,替换成直接引用。

3.初始化

    如果类被首次主动使用,就需要对该类进行初始化,即为类变量赋予正确的初始值。
    类变量的初始化通过初始化语句或者静态初始化程序块,编译器会将它们收集起来,并放到<clinit>方法中,只能被虚拟机调用进行初始化。
    并非所有的类都会拥<clinit>() 方法,在以下条件中该类不会拥有 <clinit>() 方法:
  • 该类既没有声明任何类变量,也没有静态初始化语句;
  • 该类声明了类变量,但没有明确使用类变量初始化语句或静态初始化语句初始化;
  • 该类仅包含静态 final 变量的类变量初始化语句,并且类变量初始化语句是编译时常量表达式。

4.使用

    类的使用分为主动使用和被动使用两类。
 
    被认为是主动使用的6种情况:
  • 通过new关键字创建类的实例化对象
  • 调用类的静态方法
  • 操作类中静态变量
  • 调用Java API中特定的反射方法
  • 初始化一个类的子类
  • Java虚拟机的启动类,即拥有main方法且是启动方法的类

  除了上面6种情况以外的使用,都是被动使用,例如:
  • 引用父类的静态字段,只会引起父类的初始化,而不会引起子类的初始化
  • 定义类数组
  • 使用类的常量
 注意:只有主动使用才会触发类的初始化,而被动使用不会触发类进行初始化。

5.卸载

   被装载的类型会在方法区中占据内存空间。如果程序不再引用某类型,该类型就会变成不可触及,可以被卸载。
 
  判断类型的Class实例是可触及的两种方式:
  • 程序保持对该Class实例的明确引用
  • 堆中可触及的对象在方法区中对应的类型数据或超类型指向该Class实例

  注意:启动类装载器装载的类型永远是可以触及的,所以永远不会被卸载。只有使用自定义类装载器装载的类型才会变成不可触及,从而被虚拟机卸载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值