【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言:

Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程 。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。

目录

​编辑前言:

类的生命周期

类的加载阶段

核心任务

连接阶段

验证(Verification)

准备(Preparation)

解析(Resolution)

初始化阶段

[() 方法特性](#() 方法特性)

不会导致初始化

初始化触发条件(严格规定)

使用阶段

卸载阶段

面试题

总结


类的生命周期

一个类的生命周期分为五个阶段,分别是加载,连接,初始化,使用和卸载。

类的加载阶段

加载是将类的字节码文件(.class)加载到 JVM 内存的过程,类加载器会通过不同的形式,去得到字节码文件的内容,然后通过JVM,把内容加载到方法区和堆区,而我们开发者只能访问到堆区的内容,方法区我们是访问不到的,堆区的内容是字节码文件的核心内容。

核心任务

  1. 查找字节码

    • 通过类的全限定名查找字节码文件

    • 搜索路径:类路径(classpath)、JAR 文件、网络资源等

  2. 创建类结构

    • 解析字节码并创建对应的类数据结构

    • 在方法区(元空间)存储类的运行时常量池、字段和方法信息

  3. 创建 Class 对象

    • 在堆内存中创建 java.lang.Class 对象

    • 该对象作为访问类元数据的入口

连接阶段

在加载阶段结束后进入连接阶段,连接阶段分为三个子阶段,确保类字节码的正确性和可用性

验证(Verification)

确保字节码符合 JVM 规范和安全要求:

  • 文件格式验证:魔数(0xCAFEBABE)、版本号等

  • 元数据验证:语义检查(是否有父类、final类是否被继承等)

  • 字节码验证:数据流和控制流分析

  • 符号引用验证:检查引用的类、字段和方法是否存在

准备(Preparation)

为类变量分配内存并设置初始值:

  • 静态变量分配

    • 在方法区分配内存

    • 设置类型默认值(零值)

      • int → 0

      • boolean → false

      • 引用类型 → null

  • 特殊处理

    • static final 常量:直接赋程序指定值

      // 准备阶段直接赋值
      public static final int MAX = 100;

解析(Resolution)

将符号引用转换为直接引用:

  • 符号引用:用一组符号描述引用的目标

  • 直接引用:指向目标的指针、偏移量或句柄

初始化阶段

执行静态代码块的内容和给静态变量赋值,以字节码文件视角就是执行<clinit>方法

<clinit>() 方法特性

  1. 自动生成

    • 编译器收集所有类变量赋值静态代码块

    • 按源代码顺序合并生成

  2. 线程安全

    • JVM 保证只有一个线程执行初始化

    • 其他线程会阻塞等待完成

  3. 父类优先

    • 执行子类的 <clinit>()

    • 必须先执行父类的 <clinit>()

不会导致初始化

  1. 无静态代码块且无静态变量赋值语句。
  2. 有静态变量的声明,但是没有赋值语句。
  3. 静态变量的定义使用final关键字,这类变量会在准备阶段直接初始化 。
  4. 直接访问父类的静态变量,不会触发子类的初始化。
  5. 数组的创建不会导致数组中元素的类进行初始化。

初始化触发条件(严格规定)

  1. new 实例化对象

  2. 访问类的静态变量(非 final 常量)

  3. 调用类的静态方法

  4. 反射调用(Class.forName())

  5. 初始化子类时(父类需先初始化)

  6. JVM 启动时的主类

  7. MethodHandle 解析结果涉及静态方法

使用阶段

类的初始化之后,它就可以在程序中自由使用了。这包括创建实例、调用方法和访问字段等操作。在这个阶段,对象会被创建和操作,它们各自也会经历自己的生命周期。

卸载阶段

在某些情况下,当一个类不再需要时,它会被卸载。类的卸载发生在垃圾收集的过程中,当确定某个类的Class对象不再被引用,且对应的ClassLoader实例也不再存在时,JVM就可能卸载这个类。但是,在常见的Java应用中,由于系统类加载器加载的类一直会被引用,所以这些类通常只有在JVM停止运行时才会被卸载。

面试题

说出一下代码的运行结果:

复制代码
public class Demo01 {
    public static void main(String[] args) {
 
        System.out.println(B02.a);
    }
}
class A02
{
    static int a=0;
    static{
        System.out.println("A02");
        a=1;
    }
}
class B02 extends A02{
    static{
        System.out.println("B02");
        a=2;
    }
}

运行结果为A02 1 原因是因为:访问父类的静态变量,只初始化父类

复制代码
public class Demo01 {
    public static void main(String[] args) {
        new B02();
        System.out.println(B02.a);
    }
}
class A02
{
    static int a=0;
    static{
        System.out.println("A02");
        a=1;
    }
}
class B02 extends A02{
    static{
        System.out.println("B02");
        a=2;
    }
}

首先执行main方法,new了B02所以要初始化它,但是它是子类,所以要先初始化A02,首先给赋值为0然后打印出A02,在给a赋值1,在初始化B02,打印出B02,a赋值为2,然后打印出a的值2

运行结果是:A02 B02 2

复制代码
public class test5 {
    public static void main(String[] args) {
 
        System.out.println("A");
        new test5();
        new test5();
    }
    public  test5()
    {
        System.out.println("B");
    }
    {
        System.out.println("C");
    }
    static {
 
        System.out.println("D");
    }
 
}
  1. 先执行test5这个类的静态代码块输出D
  2. 在执行main方法打印A
  3. 在初始化test5,执行构造器方法和代码块方法,但是代码块先执行所以第一个new执行CB
  4. 第二个new执行CB
  5. 结果:DACBCB

以上面试题你都做对了吗?

总结

Java类的生命周期包括:加载(将字节码加载到内存,生成Class对象)、连接(验证字节码、准备静态变量内存并赋默认值、解析符号引用)、初始化(执行静态代码块和赋值)、使用(创建实例、调用方法)、卸载(类不再使用时被回收)。按此顺序完成从加载到销毁的完整过程。

学习类的生命周期,能让我们对java语言有一个更深的认识,也能让我们在面试中多一点机会。

总之,类的生命周期从加载到卸载,经历了多个阶段,每个阶段都有特定的任务和目标。理解类的生命周期有助于我们更好地理解和管理Java程序的运行机制。

感谢你的阅读,希望文章能给你带来帮助,你的阅读点赞就是我最大的动力。

相关推荐
甜甜的资料库27 分钟前
基于微信小程序的作业管理系统源码数据库文档
java·数据库·微信小程序·小程序
~Yogi2 小时前
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
学习·spring·缓存
Moonnnn.4 小时前
【单片机期末】单片机系统设计
笔记·单片机·嵌入式硬件·学习
行云流水剑5 小时前
【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南
linux·学习·安全
有梦想的骇客6 小时前
书籍“之“字形打印矩阵(8)0609
java·算法·矩阵
why1516 小时前
微服务商城-商品微服务
数据库·后端·golang
yours_Gabriel7 小时前
【java面试】微服务篇
java·微服务·中间件·面试·kafka·rabbitmq
门前云梦8 小时前
《C语言·源初法典》---C语言基础(上)
c语言·开发语言·学习
hashiqimiya8 小时前
android studio中修改java逻辑对应配置的xml文件
xml·java·android studio
liuzhenghua669 小时前
Python任务调度模型
java·运维·python