跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 虚拟机核心机制:类加载与垃圾回收详解

Java 虚拟机通过类加载机制管理类的生命周期,涵盖加载、验证、准备、解析和初始化等阶段。双亲委派模型确保了类的唯一性与安全性。对象创建涉及内存分配、零值初始化及构造器执行。垃圾回收(GC)自动管理内存,通过可达性分析判断对象存活状态。主流回收算法包括标记清除、标记整理和复制算法。新生代常用复制算法,老年代多用标记整理或并发清除。G1 收集器相比 CMS 在可预测停顿时间和内存碎片处理上更具优势,适合现代多核环境下的应用。

暖阳发布于 2026/3/16更新于 2026/8/2245 浏览
Java 虚拟机核心机制:类加载与垃圾回收详解

1. 类初始化和类加载

1.1 创建对象的过程

在 JVM 中,创建一个新对象并非简单的内存分配,它包含几个关键步骤。当执行到 new 关键字时,JVM 会先检查目标类是否已加载。若未加载,则触发类加载流程;若已加载,则继续后续步骤。

接下来是在堆内存中分配空间,随后将对象实例变量初始化为零值(对象头除外)。之后需要对对象头进行必要的设置,比如记录哈希码、分代年龄等信息。最后,才会执行对应的构造方法(init 方法)。

  • 类加载:JVM 在执行到 new 关键字的时候,会先进行对应类的类是否加载,如果没有加载,那么就会先执行类加载,然后再执行 new 关键字。
  • 分配内存空间:在堆中分配一段空间给对应对象。
  • 初始化零值操作:给对象的空间内的对应成员初始化为零值(对象头除外)。
  • 进行必要的设置:比如说:给对象头设置一些信息,类的元数据,对象的年龄,对象的哈希码。
  • 执行 init 方法:执行对应的构造方法。

1.2 对象的生命周期

对象的生命周期可以概括为创建、使用、销毁三个阶段。

  • 创建:即上述的类加载与对象实例化过程。
  • 使用:调用该对象的成员方法或访问属性。
  • 销毁:当对象没有被引用了,就会被看作垃圾进行回收。

1.3 类加载器

JVM 提供了三种主要的类加载器,它们各司其职:

  • 启动类加载器:负责加载 Java 核心库里面的类,通常由 C++ 实现。
  • 扩展类加载器:加载一些扩展的类,比如说框架的类。
  • 应用程序类加载器:加载用户自己手动创建的类,也就是我们日常开发中最常接触的。

1.4 双亲委派模型

这是类加载器的核心原则,遵循'向上委派,向下加载'的策略。

如果一个类加载器收到了加载类的任务,不会自己先执行,而是往上委派给自己的父类,依次类推,直到委派给最终的父类也就是启动类加载器。然后从启动类加载器开始,判断该类是否被自己加载,如果能直接返回即可,如果不能继续往下加载(抛给子类),依次类推。

这种机制主要有以下作用:

  1. 保证类的唯一性:向上委派、向下加载的方式,保证了一个类不会被重复加载,并且保证一个类只会被一个类加载器加载。
  2. 保证安全性:如果用户自己编写了一些类,类的全限定名与 Java 核心库中的类一致,可能会出现优先加载用户的类,从而间接导致核心类被用户修改了。通过向上委派、向下加载的方式从上开始加载,保证了类的安全性。
  3. 形成了隔离和分层的效果:不同的类加载器负责不同的类,既不会重复加载,也保证了高效性。
  4. 简化了类加载流程:这种方式保证了一个类只能加载一次并且不同的类加载器负责不同的类,从而简化了流程。

1.5 类加载的过程

从大体上类加载分为五步:类加载、连接、初始化、使用、卸载。细分又有七步:类加载、验证、准备、解析、初始化、使用、卸载。

  • 类加载:通过类的全限定名找到对应的二进制字节码文件,将该文件转换到内存形成创建对象实例的模板。
  • 验证:验证该二进制字节码是否符合 JVM 规范,比如说校验魔术、主版本号等等。具体包括文件格式校验、元数据验证、字节码验证、符号引用验证。
  • 准备:给该类的静态变量赋一些初始化值。
  • 解析:将原来的符号引用转为直接引用。
  • 初始化:执行构造器方法,执行父类的静态成员、子类的静态成员、父类的构造方法、子类的构造方法。
  • 使用:用户使用。
  • 卸载:判断该类没有被引用即可卸载,主要看三个方面:该类里面的所有实例对象都已经被回收了、该类的 ClassLoader 对象已经被回收了、该类的实例没有被引用。

2. 垃圾回收

2.1 垃圾回收介绍

以前传统的开发人员需要进行一个对内存的手动释放,而垃圾回收就是可以自动的对内存进行回收。它既提高了开发效率,也避免了一些问题,比如内存溢出、内存泄漏。

2.2 触发垃圾回收的方式

GC 的触发方式主要有以下几种:

  1. 内存不足:当内存不足的时候,会触发直接垃圾回收机制。
  2. 手动执行:开发人员自己手动指定执行,例如调用 System.gc()。
  3. JVM 调参:通过调参可以来指定垃圾回收的行为。
  4. 内部策略:垃圾回收内部可能指定了创建对象的数量和内存使用情况,如果超过一定的阈值就会触发垃圾回收。

2.3 判断垃圾的方法

判断对象是否为垃圾主要有两种方法:

  • 引用计数法:给每次对象分配一个计数器,如果该对象被一个对象引用,那么就会将计数器进行加一。如果该对象没有被引用,那么此时计数器为 0,则被判断为可以被回收。不过这种方法无法解决循环引用的问题。
  • 可达性分析法:从 GC Root 出发找对应对象进行标记,如果有一个对象没有被标记(代表没有被直接引用或间接引用),那么该对象可以被回收。GC Root 对象包括:Java 的核心库类、调用本地方法的类、活跃线程的类等。

2.4 垃圾回收算法

主流的垃圾回收算法包括标记清除、标记整理和复制算法。

  • 标记清除算法:对引用的对象进行标记,然后进行清除。注意这里不是真正的清除,而是记录其对象的起始地址和结束地址到一个地址表中,下次要添加新对象时会先从表中找,找到一个适合大小的就会进行覆盖。好处是速度快,缺点是内存碎片化严重(内存不连续了,本来可以存入的对象存入不了)。
  • 标记整理算法:同理进行标记,然后再对可存活对象进行整理,最后清除。好处是避免了内存碎片化问题,缺点是速度慢。
  • 复制算法:将内存空间分为两份,一份存对象 from,一份为空 to。当要回收时,复制可存活对象移入为空的内存空间 to 中(移入既整理),然后对存对象的空间 from 整体清除,然后名称 from 和 to 换过来。好处是避免了内存碎片化问题,缺点是内存使用率不高。

2.5 垃圾回收器

根据作用范围不同,收集器也有所区别:

  • 新生代:Serial、ParNew、Parallel Scavenge,都是使用的复制算法。

  • 老年代:Serial Old(标记整理)、CMS(标记清除)、Parallel Old(标记整理)。

  • 整个堆:G1(整体标记整理,细分区域使用复制)。

  • Serial GC:串行的收集器。

  • ParNew/CMS:并行的收集器,重响应时间快的特点。

  • Parallel GC:并行的收集器,重吞吐量高的特点。

  • G1:并行的收集器,比较平衡。

2.6 minorGC、majorGC、fullGC

  • minorGC:

    • 范围:作用于新生代。
    • 作用时机:当新生代的 Eden 区空间无法装入新创建的对象时,就会触发一次 minorGC,并且每触发一次 minorGC,其存活对象的年龄加一。
    • 细节:作用时间短,次数多。
  • majorGC:

    • 范围:作用于老年代。
    • 作用时机:当新生代的对象需要移入老年代时,发现其空间不足,那么就会触发 majorGC。
    • 细节:作用次数不多,而不常使用。
  • fullGC:

    • 范围:作用于整个堆。
    • 作用时机:当新生代对象需要移入老年代时,发现其空间不足,会触发 minorGC,触发之后,如果还是老年代空间不足,那么就会触发 fullGC,对整体进行整理。
    • 细节:作用次数不多,作用时间长。

2.7 CMS 与 G1 的区别

方面CMSG1
作用范围作用于老年代作用于整个堆
STW 的时间CMS 是重响应时间快的,STW 的时间会更短G1 可以对 STW 时间进行一个可预测的操作
内存碎片化CMS 使用的是标记清除算法,会造成内存碎片化问题G1 使用的是标记整理算法,不会造成内存碎片化问题
垃圾回收过程初始标记、并发标记、重新标记、并发清理初始标记、并发标记、最终标记、筛选回收(如果并发标记中出现了对象引用改变,会将其对象引用存入一个队列中,直到最终标记时从队列进行进一步的筛选)
浮动垃圾它使用的是并发清理,那么如果垃圾回收的速度低于产生垃圾的速度,那么就会出现问题,从而导致 CMS 转变为 Serial,并且也由于在回收的过程中会产生一些浮动垃圾,因此需要一部分空间来存储对应的浮动垃圾它虽然也会产生垃圾,但是不会出现该问题,并且它是使用的多个垃圾回收器进行垃圾回收,效率更高

目录

  1. 1. 类初始化和类加载
  2. 1.1 创建对象的过程
  3. 1.2 对象的生命周期
  4. 1.3 类加载器
  5. 1.4 双亲委派模型
  6. 1.5 类加载的过程
  7. 2. 垃圾回收
  8. 2.1 垃圾回收介绍
  9. 2.2 触发垃圾回收的方式
  10. 2.3 判断垃圾的方法
  11. 2.4 垃圾回收算法
  12. 2.5 垃圾回收器
  13. 2.6 minorGC、majorGC、fullGC
  14. 2.7 CMS 与 G1 的区别
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Stable Diffusion 完整训练与推理流程详解(含伪代码)
  • KoboldAI 安装与配置指南
  • Java 8 新日期时间 API 核心用法详解
  • JavaScript 运算符与流程控制全解析
  • WebGL 三维地下空间可视化技术深度解析
  • 滑动窗口算法实战:水果成篮与字母异位词查找
  • 大模型 RAG 技术深度解析:从入门到进阶
  • Python 30 行实现公开接口数据本地化存储
  • C++11 手写 Promise 实现与 std::promise 对比
  • 西门子 S7-1500 PLC 与 Fanuc 机器人焊装系统 Profinet 集成
  • 受限内网环境下 TensorFlow 镜像拉取优化方案
  • 二分查找应用:寻找旋转排序数组最小值与缺失数字
  • 《GPT 图解大模型是怎样构建的》:从 NLP 演进到 GPT 实战
  • LangChain 框架简介、核心模块与文档指南
  • 银河麒麟 V11-2503 安装指南:6.6 内核与 AI 特性详解
  • Spring AI 重塑 Java 生态 AI 开发实践
  • Git Bash 详解:功能、组成、使用场景与底层原理
  • GESP 2025 年 9 月 C++ 一级认证真题与解析(单选 1-15)
  • Python 网络编程基础:Socket、TCP 与 UDP 实战指南
  • 使用 Obsidian 的 Git 插件将笔记同步到 GitHub 私有仓库

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online