Salmon的全栈知识 Salmon的全栈知识
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
npm

(进入注册为作者充电)

  • JVM基础

    • 初识JVM
    • 字节码文件详解
    • 运行时数据区
    • 垃圾回收
  • JVM实战

    • 内存调优
    • GC调优
    • 性能调优
  • JVM高级

    • GraalVM
    • 新一代的GC
    • 揭秘Java工具
  • JVM原理

    • 栈上的数据存储
    • 对象在堆上是如何存储的?
    • 方法调用的原理
    • 异常捕获的原理
    • JIT即时编译器
    • 垃圾回收器原理
  • JVM面试

    • 什么是JVM?
    • 了解过字节码文件的组成吗?
    • 说一下运行时数据区
    • 哪些区域会出现内存溢出,会有什么现象?
    • JVM在JDK6-8之间在内存区域上有什么不同
    • 类的生命周期
      • 加载阶段
      • 连接阶段
      • 初始化阶段
      • 卸载阶段
      • 总结
    • 什么是类加载器?
    • 什么是双亲委派机制
    • 如何打破双亲委派机制
    • Tomcat的自定义类加载器
    • 如何判断堆上的对象没有被引用??
    • JVM 中都有哪些引用类型?
    • ThreadLocal中为什么要使用弱引用?
    • 有哪些常见的垃圾回收算法?
    • 有哪些常用的垃圾回收器?
    • 如何解决内存泄漏问题?
    • 常见的JVM参数?
  • 《JVM》笔记
  • JVM面试
Salmon
2024-03-12
目录

类的生命周期

  • 关联课程内容

    • 基础篇-类的生命周期-加载阶段
    • 基础篇-类的生命周期-连接阶段
    • 基础篇-类的生命周期-初始化阶段
    • 基础篇-方法区的回收
  • 回答路径

    • 加载
    • 连接(验证、准备、解析)
    • 初始化
    • 卸载

类的生命周期分为以下几个阶段:

img

# 加载阶段

1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。

​ 程序员可以使用Java代码拓展的不同的渠道。

img

2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到内存的方法区中。在方法区生成一个InstanceKlass对象,保存类的所有信息。

img

3、在堆中生成一份与方法区中数据类似的java.lang.Class对象, 作用是在Java代码中去获取类的信息。

img

比如这段代码中,就会访问堆中的Class对象:

img

# 连接阶段

连接阶段分为三个小阶段:

img

连接(Linking)阶段的第一个环节是验证,验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段一般不需要程序员参与。

主要包含如下四部分,具体详见《Java虚拟机规范》:

1.文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。

2.元信息验证,例如类必须有父类(super不能为空)。

3.验证程序执行指令的语义,比如方法内的指令执行到一半强行跳转到其他方法中去。

4.符号引用验证,例如是否访问了其他类中private的方法等。

准备阶段为静态变量(static)分配内存并设置初值。final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。

img

解析阶段主要是将常量池中的符号引用替换为直接引用。符号引用就是在字节码文件中使用编号来访问常量池中的内容。直接引用不在使用编号,而是使用内存中地址进行访问具体的数据。

img

# 初始化阶段

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

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

img

以如下代码为例:

package q3loadclass;

public class Demo1 {
    public static int value = 1;
    static {
        value = 2;
    }
    {
        value = 3;
    }
    public static void main(String[] args) {
        new Demo1();
        System.out.println(value);
    }
}

1.连接的准备阶段value赋初值为0 2.初始化阶段执行clinit方法中的指令,value赋值为2 3.如果创建对象,会执行对象的init方法,value赋值为3 (类中代码块中的内容被放到了构造方法中)

# 卸载阶段

判定一个类可以被卸载。需要同时满足下面三个条件:

1、此类所有实例对象都已经被回收,在堆中不存在任何该类的实例对象以及子类对象。

img

2、加载该类的类加载器已经被回收。

img

3、该类对应的 java.lang.Class 对象没有在任何地方被引用。

img

# 总结

img

上次更新: 2025/03/09, 18:29:07
JVM在JDK6-8之间在内存区域上有什么不同
什么是类加载器?

← JVM在JDK6-8之间在内存区域上有什么不同 什么是类加载器?→

Theme by Vdoing | Copyright © 2022-2025 Salmon's Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式