4 类的生命周期

4 类的生命周期

​ 类的生命周期描述了一个类加载、使用、卸载的整个过程

​ 类的生命周期包括五个阶段:加载、连接、初始化、使用、卸载

  • 加载

    • 加载阶段第一步是类加载器根据类的全限定名通过不同的渠道(本地文件、动态代理生成等)以二进制流的方式获取字节码信息
    • 类加载器在加载完类之后,java虚拟机会将字节码中的信息保存到方法区中。生成一个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能,比如:多态的信息
    • java虚拟机还会在中生成一份与方法区中数据类似的java.lang.Class对象静态字段会保存在中(JDK1.8以后)
    • 在堆中生成的Class对象的好处:开发者不需要去访问方法区,访问Class对象即可,方法区中的信息更多
  • 连接

    • 验证

      验证内容是否符合jvm规范

    • 准备

      给静态变量赋初始值不是给它赋自己定义的值

      例如:public static int i = 2;,在准备阶段的时候,栈中的i的值赋予了初始值0,还没有赋值2

      但如果是用了final修饰,在准备阶段就直接赋了自己定义的值。

    • 解析

      将常量池中的符号引用替换成指向内存的直接引用

  • 初始化重要,程序员可以干涉)

    • 初始化阶段会执行静态代码块中的代码,并为静态变量赋值

    • 初始化阶段会执行字节码文件中的clinit部分的字节码指令

    • 以下几种方式会导致类的初始化:

      • 1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化
      • 2.调用Class.forName(String className)
      • 3.new一个该类的对象时
      • 4.执行Main方法的当前类

      例:

      public class Test2 {
      
      public static void main(String[] args) {
        System.out.println("A");
        new Test2();
        new Test2();
      }
      
      public Test2(){
        System.out.println("B");
      }
      
      {
        System.out.println("C");
      }
      static {
        System.out.println("D");
      }
      }
      //输出结果为:
      D
      A
      C
      B
      C
      B
      
    • 以下几种情况不会初始化

      • 1.无静态代码块且无静态变量赋值语句
      • 2.有静态变量的声明,但是没有赋值语句
      • 3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化
    • 父类和子类的初始化

      • 直接访问父类的静态变量,不会触发子类的初始化子类的
      • 初始化clinit调用之前,会先调用父类的clinit初始化方法
    • 数组的创建不会导致数组中元素的类进行初始化

    //数组的创建不会导致数组中元素的类进行初始化
    public class TestArrayInit {
    
    public static void main(String[] args) {
      TestArrayInit_A[] arr = new TestArrayInit_A[10];
    }
    }
    
    class TestArrayInit_A {
    static {
      System.out.println("TestArrayInit_A的静态代码块运行");
    }
    }
    
    • final修饰的变量如果赋值的内容需要执行指令才能得出结果,会执行clinit方法进行初始化
    public class TestFinalInit {
    public static void main(String[] args) {
      System.out.println(TestFinalInit_A.a);
    }
    }
    
    class TestFinalInit_A{
    public static final int a = Integer.valueOf(1);
    static {
      System.out.println("静态代码块运行了");
    }
    }
    //输出结果:
    静态代码块运行了
    1
    
  • 结合类连接和初始化阶段思考以下两个案例:

public class HSDBDemo {

static {
  i = 10;
}

public static int i=2;

public static void main(String[] args) throws IOException {
  HSDBDemo hsdbDemo = new HSDBDemo();
  //输出结果位2
  System.out.println(i);   
}
}
public class HSDBDemo {

static {
  i = 10;
}

public static int i;

public static void main(String[] args) throws IOException {
  HSDBDemo hsdbDemo = new HSDBDemo();
  //输出结果为10
  System.out.println(i);
}
}
  • 使用

  • 卸载

posted @   渺阴丶  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示