介绍

一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段:
简述JAVA类的生命周期 随笔 第1张

加载

主要是:把类的信息加载到方法区中,并在堆中实例化一个Class对象。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

加载方式

根据类的全路径加载class文件
从jar的包中读取class文件
根据一定的规则实时生成,比如设计模式中的动态代理模式,就是根据相应的类自动生成它的代理类。

加载的时期

不是jvm启动就加载,而是在真是使用的时候才会触发加载。

  • new 一个类的时候
  • 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
  • 这个类是程序的入口类
  • 对这个类进行反射的时候(执行了上面的行为)

连接

一般会跟加载阶段和初始化阶段交叉进行。

验证

验证一下这个类是否合法,

  • 字节码格式是否合法
  • 变量和方法是否有重复
  • 继承和实现是否符合标准
    。。。

准备

给静态变量赋默认的初始值(不包括非静态变量)

解析

把符合引用转换为直接引用。
比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,
jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。
这里show就是符号引用,而c17164就是直接引用。
在解析阶段jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。

初始化

时机

和加载的时机一样,更准确的说初始化之前必须先经过加载,所以他们基本一样

  • new 一个类的时候
  • 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
  • 这个类是程序的入口类
  • 对这个类进行反射的时候(执行了上面的行为)

过程

按照顺序自上而下运行类中的【变量赋值语句】和【静态语句】,
如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。
简述JAVA类的生命周期 随笔 第2张

使用

使用阶段包括主动引用和被动引用。

主动引用(会引起类的初始化)

  • new 一个类的时候
  • 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
  • 这个类是程序的入口类
  • 对这个类进行反射的时候(执行了上面的行为)

被动引用(不会引起类的初始化)

引用父类的静态字段
定义类数组
引用类的常量

例如

public class TestClassInit {
    static {
        System.out.println("初始化InitClass");
    }
    public static String staticA = null;
    public final static String finalB = "b";
    public static void staticMethod(){}
}
public class Test {
    public static void main(String args []){
        //主动引用
        //new 一个类的时候
        TestClassInit tct=new TestClassInit();
        //读取静态变量
        String staticA=TestClassInit.staticA;
        //设置静态变量
        TestClassInit.staticA="A";
        //调用静态方法
        TestClassInit.staticMethod();

        //被动引用
        //定义类数组,不会引起类的初始化
        TestClassInit[] tcts=new TestClassInit[10];
        //引用类的常量,不会引起类的初始化
        String finalB=TestClassInit.finalB;
    }
}

卸载

满足下面请看才会卸载类:

  • java堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄