JVM随记
一、JVM垃圾的来源平时开发写的接口数据流转一般是从前端发起HTTP请求到后端前端 ↓ Controller ↓ Service ↓ Dao ↓ 数据库我们在对接口进行实现的时候会创建很多对象例如User user new User(); UserDTO userDTO new UserDTO();这些对象一般是存放在堆内存中的。而我们在方法中定义的局部变量比如User user new User();这里的user是一个对象引用这个引用一般存放在当前线程的栈帧中而真正的User对象存放在堆中。可以简单理解为栈 user ─────────────→ 堆 User对象当方法执行结束以后如果没有其他地方再引用这个User对象那么这个对象就没有办法再被程序访问到了。这时候这个对象就会变成垃圾对象。但是需要注意对象变成垃圾并不代表JVM马上就会把它回收。什么时候回收是由垃圾回收器决定的。二、JVM如何识别和清除垃圾Java中的线程是共享堆内存的但是每一个线程都有自己的栈内存。每一个线程在执行方法的时候都会创建一个对应的栈帧。栈帧主要用来保存当前方法执行过程中需要使用的数据例如局部变量对象引用操作数等例如public void test() { User user new User(); }可以简单理解为线程栈 test()栈帧 ┌─────────────┐ │ user │ ──────────→ User对象 └─────────────┘ ↑ │ 堆JVM在判断一个对象是不是垃圾的时候并不是简单地看“有没有一个变量指向它”而是使用可达性分析算法。它会从一些特殊的对象也就是GC Roots开始往下寻找。例如GC Roots ↓ User引用 ↓ User对象 ↓ Address对象那么User对象 → 存活 Address对象 → 存活因为它们都可以从GC Roots找到。如果一个对象GC Roots ↓ 找不到这个对象那么这个对象就会被认为是不可达对象也就是垃圾对象。常见的GC Roots包括当前线程栈帧中的引用静态变量引用常量引用一些JNI引用等所以这里需要注意GC Roots不只是线程栈中的引用只是线程栈中的局部变量引用是我们最容易理解的一种。三、JVM垃圾分类与分代处理Java程序运行的时候会创建大量对象。但是这些对象的生命周期是不一样的。有一些对象刚创建没多久就没用了。例如用户注册 ↓ 创建User对象 ↓ 创建UserDTO对象 ↓ 数据处理完成 ↓ 请求结束 ↓ 这些临时对象可能就不再使用了这些对象的生命周期比较短。还有一些对象可能会存活很长时间。例如用户登录 ↓ 用户信息保存到Session ↓ 长时间存在所以JVM根据对象存活时间的不同把堆内存进行了分代。经典的分代模型堆 │ ├── 新生代 │ ├── Eden │ ├── Survivor 0 │ └── Survivor 1 │ └── 老年代可以简单理解成新创建的对象 ↓ 新生代 ↓ 存活时间越来越长 ↓ 老年代四、新生代的特点以及它的回收算法新生代最大的特点就是对象创建非常频繁但是大部分对象很快就会变成垃圾。例如一次HTTP请求请求进来 ↓ 创建A对象 创建B对象 创建C对象 创建D对象 ↓ 请求处理完成 ↓ A、B、C、D可能很快就没有用了所以新生代里面虽然对象创建得很多但是经过一次GC之后真正存活下来的对象通常比较少。因此新生代比较适合使用复制算法。1. Eden区新创建的对象通常会首先进入Eden区。例如Eden [A][B][C][D][E]当Eden空间不够的时候就会进行一次Young GC。JVM会进行可达性分析。假设A → 存活 B → 垃圾 C → 存活 D → 垃圾 E → 存活那么Eden [A][B][C][D][E] ↓ ↓ ↓ 存活 垃圾 存活 ↓ 复制到Survivor最终Eden Survivor 清空 [A][C][E]Eden里面的垃圾直接被回收存活的对象复制到Survivor区。五、为什么会有S0和S1Survivor区实际上还有两个S0 S1它们主要是为了配合复制算法使用。例如第一次GCEden S0 ↓ 找到存活对象 ↓ 复制到S1然后下一次GCEden S1 ↓ 找到存活对象 ↓ 复制到S0再下一次Eden S0 ↓ 复制到S1所以它们会不断进行交换Eden ↓ S0 ↓ S1 ↓ S0 ↓ S1 ↓ ......这里的核心思想就是每次GC只把存活的对象复制到另外一个Survivor区然后把原来的区域整体清空。六、对象什么时候进入老年代对象每经过一次Young GC如果还存活那么它的年龄一般就会增加。例如第一次Young GC 对象还活着 年龄 1 第二次Young GC 对象还活着 年龄 1 第三次Young GC 对象还活着 年龄 1这样不断增加。当对象达到一定的年龄之后就可能从年轻代进入老年代。很多资料中会说对象年龄达到15岁就进入老年代。这个说法不够准确。更准确地说经典HotSpot情况下年龄阈值常见是15但并不是说所有情况下都一定15次GC之后进入老年代。还可能因为Survivor空间不够对象太大垃圾收集器的具体策略导致对象提前进入老年代。所以记成新对象 ↓ Eden ↓ Young GC ↓ Survivor ↓ 继续存活 ↓ 年龄增加 ↓ 满足晋升条件 ↓ 老年代就可以了。七、老年代的特点以及它的回收算法老年代里面的对象一般都是存活时间比较长的对象。也就是说新生代 创建很多对象 ↓ 大部分很快死亡 ↓ 少部分存活而老年代长期存活的对象比较多 ↓ 所以存活对象比例通常比较高因此老年代的回收和新生代是不太一样的。传统的垃圾回收算法里面老年代经常会使用标记-清除标记-整理八、标记-清除算法标记-清除其实很好理解。假设老年代里面有[A][B][C][D][E][F]经过可达性分析之后A → 存活 B → 垃圾 C → 存活 D → 垃圾 E → 存活 F → 垃圾第一步就是标记垃圾对象。[A][X][C][X][E][X]第二步清除垃圾对象。[A][空][C][空][E][空]这就是标记-清除。它的问题就是清除垃圾之后会产生内存碎片。例如[A][空][C][空][E][空]虽然这里总共有3块空间是空的。但是如果现在来了一个需要连续空间的大对象[大对象]可能还是放不进去。所以就出现了明明还有空间但是因为空间不连续所以无法存放对象。这就是内存碎片。九、标记-整理算法为了解决标记-清除产生的内存碎片问题就可以使用标记-整理。还是[A][空][C][空][E][空]先标记存活对象[A][C][E]然后把存活对象移动到一起[A][C][E][空][空][空]这样存活对象集中在前面 空闲空间集中在后面这样就可以减少内存碎片。所以标记-清除 [A][空][C][空][E][空] ↓ 产生内存碎片而标记-整理 [A][空][C][空][E][空] ↓ [A][C][E][空][空][空]这样空间就更加连续。十、把整个JVM垃圾回收串起来整个过程其实可以理解成Java程序运行 ↓ 不断创建对象 ↓ 对象进入Eden ↓ Eden空间不足 ↓ Young GC ↓ ┌──────────────┐ │ │ 垃圾对象 存活对象 ↓ ↓ 回收 Survivor ↓ 再次Young GC ↓ 年龄增加 ↓ 满足晋升条件 ↓ 老年代 ↓ 老年代GC ↓ 标记 / 清除 / 整理

相关新闻

只会 Python 基础,能做 AI 开发吗?看完岗位要求我悟了

只会 Python 基础,能做 AI 开发吗?看完岗位要求我悟了

摘要:本文基于 2026 年最新 AI 应用开发岗位 JD 的深度拆解,回答一个困扰无数 Python 初学者的核心问题:只会 Python 基础,到底能不能做 AI 开发?文章系统分析了 AI 应用岗的真实能力要求、Python 基础与岗位需求之间的…

2026/10/4 7:25:59 阅读更多 →
MR25H40CDF铁电存储器与ATmega1284工业级协同设计指南

MR25H40CDF铁电存储器与ATmega1284工业级协同设计指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 7:25:59 阅读更多 →
TreeATE测试脚本开发避坑指南:从环境搭建到仪器通信的稳定写法

TreeATE测试脚本开发避坑指南:从环境搭建到仪器通信的稳定写法

做测试开发这些年,我见过太多同事在TreeATE上浪费时间的案例。印象最深的一次,一个做电源测试的兄弟,单独跑Python脚本一切正常,一放进TreeATE的测试序列里就时好时坏,成功率只有七成,他调了一整天都没想明…

2026/10/4 7:25:59 阅读更多 →

最新新闻

C++轻量级FBX查看器:解析、渲染、交互

C++轻量级FBX查看器:解析、渲染、交互

FBX这个名字,做过三维内容的人都不会陌生。它是Autodesk推出的一种通用模型交换格式,市面上几乎所有DCC软件——3ds Max、Maya、Blender、Substance Painter——都能导入导出它,游戏引擎、渲染器、资源管线的对接也基本绕不开它。我这个“C 简…

2026/10/4 8:28:45 阅读更多 →
NTP与chrony:Linux服务器时钟同步配置、诊断与生产故障排查实践

NTP与chrony:Linux服务器时钟同步配置、诊断与生产故障排查实践

时钟同步这个事,说来也怪,平时没人觉得它重要,可一旦出问题,你往往不是第一时间想到它。上个月我处理过一起告警:一套内部系统的HTTPS证书反复报“未生效”,运维把证书换了两次,问题依旧。最后查…

2026/10/4 8:28:45 阅读更多 →
从零搭建AI工程全链路:数据、模型、部署与踩坑实录

从零搭建AI工程全链路:数据、模型、部署与踩坑实录

很多想做 AI 工程的人,最先搜到的往往是各种“XX天速成”“调包侠指南”,但那些东西要么太浅、要么直接把你往别人的 API 上引。真正的 AI 工程,不是会调几个 Python 包、跑通几个 Notebook 就完事儿的,它牵扯到数据怎么管、模型怎…

2026/10/4 8:28:45 阅读更多 →
JavaWeb课程设计实战:Servlet调用翻译API与Redis缓存避坑指南

JavaWeb课程设计实战:Servlet调用翻译API与Redis缓存避坑指南

简介:这份资源面向JavaWeb初学者与课程设计开发者,围绕“调取第三方API实现在线翻译”这一典型场景,提供一套可运行的完整项目源码。内容涵盖前端Cookie缓存、后端Servlet与JSP协同、Redis缓存加速、MVC分层设计,以及API限流、错误…

2026/10/4 8:28:45 阅读更多 →
3名资深律师 2026上海上市公司股东离婚实务评测

3名资深律师 2026上海上市公司股东离婚实务评测

上市公司股东的离婚分割,与普通家庭最大的不同在于两点:股份有公开市价、过户有专门的业务通道,但每一步都受证券监管规则的约束。这份评测从三个维度复盘三名资深律师或团队在该场景下的实务表现。背景数据:上海市民政局公布的数…

2026/10/4 8:28:45 阅读更多 →
Cursor插件机制深度解析:TypeScript SDK与沙箱加载原理

Cursor插件机制深度解析:TypeScript SDK与沙箱加载原理

1. 项目概述:从“plugins”这个词开始,我们到底在聊什么?“plugins”这个词最近在开发者社区里高频出现,但很多人点开搜索结果后反而更迷糊了——它既不是某个具体工具的名字,也不是一个独立产品,而是一个系…

2026/10/4 8:27:44 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →