Kevin's blog Kevin's blog
首页
  • AI基础
  • RAG技术
  • 提示词工程
  • Wireshark抓包
  • 常见问题
  • 数据库
  • 代码技巧
  • 浏览器
  • 手册教程
  • 技术应用
  • 流程规范
  • github技巧
  • git笔记
  • vpn笔记
  • 知识概念
  • 学习笔记
  • 环境搭建
  • linux&运维
  • 微服务
  • 经验技巧
  • 实用手册
  • arthas常用
  • spring应用
  • javaAgent技术
  • 网站
友情链接
  • 分类
  • 标签
  • 归档

Kevin

你可以迷茫,但不可以虚度
首页
  • AI基础
  • RAG技术
  • 提示词工程
  • Wireshark抓包
  • 常见问题
  • 数据库
  • 代码技巧
  • 浏览器
  • 手册教程
  • 技术应用
  • 流程规范
  • github技巧
  • git笔记
  • vpn笔记
  • 知识概念
  • 学习笔记
  • 环境搭建
  • linux&运维
  • 微服务
  • 经验技巧
  • 实用手册
  • arthas常用
  • spring应用
  • javaAgent技术
  • 网站
友情链接
  • 分类
  • 标签
  • 归档
  • JVM性能调优

    • JVM类的加载机制
    • JVM内存模型
    • JVM对象创建与内存分配机制
    • JVM垃圾收集算法
    • JVM垃圾收集器
    • JVM调优工具以及调优实战
    • Class常量池与运行时常量池
    • arthas详解
    • JVM调优经验
    • 字节码与操作数栈
    • GCLog分析
    • jdk17新特性
    • JVM 内存分析工具 MAT及实践
    • JVM工厂运行说明书
      • 0. 工厂总览(术语对照)
      • 1. 进货与入库:类加载 → 元空间/方法区
      • 2. 下单与生产:对象创建与执行流水线
      • 3. 成品仓储:堆内存分代与晋升策略
      • 4. 清洁巡检:GC算法与实现细节
      • 5. 设备选型:主流垃圾收集器与场景
      • 6. 仪表盘与运维:参数、日志与工具
      • 7. 事故与优化:应急流程与调优要点
      • 8. 工厂隐喻一览(快速映射)
      • 9. 参考与延伸
      • 附录A 参数清单精选(整合 02/05/06)
      • 附录B MAT综合案例简版(整合 40)
      • 附录C 常见调优剧本(从症状出发)
    • Oracle:JVM & G1垃圾收集器
    • JVM学习总结
  • 并发编程

  • MySql

  • spring

  • redis

  • zookeeper

  • rabbitMQ

  • 架构

  • 锁

  • 分库分表

  • 学习笔记
  • JVM性能调优
kevin
2025-10-19
目录

JVM工厂运行说明书

# JVM工厂运行说明书

面向脑内“工厂”心智模型,对JVM的关键概念、运行流程与调优方法做一体化说明:从“进货入库”(类加载/元空间)到“下单生产”(对象创建/执行引擎),再到“成品仓储”(堆/分代)与“清洁巡检”(GC/收集器),最后覆盖“监控仪表与应急预案”(参数/日志/工具)。

# 0. 工厂总览(术语对照)

  • 原料进货/入库:类加载(加载→验证→准备→解析→初始化)
  • 原料仓/货架:元空间/方法区(类元数据、常量池、方法/字段信息等)
  • 运输/物流:类加载器体系(引导/扩展/应用/自定义,双亲委派)
  • 生产订单:new 一个对象/方法调用
  • 生产车间:执行引擎 + 线程方法栈 + 栈帧(局部变量表、操作数栈、动态链接、返回地址)
  • 流水线工艺:字节码指令集(操作数栈驱动)、静态初始化/构造过程
  • 质检/打标:零值初始化、对象头(MarkWord、Klass Pointer、对齐)
  • 成品仓储:堆(新生代/老年代、Eden/Survivor、晋升/大对象)
  • 客户/占用标签:引用类型(强/软/弱/虚)、可达性分析、GC Roots
  • 清洁巡检:GC算法(复制、标记-清除、标记-整理)、三色标记与屏障、记忆集/卡表
  • 设备选型:收集器(Serial/Parallel/ParNew/CMS/G1)与参数
  • 仪表盘:JVM启动参数、GC日志、jstat/jmap/jstack/jinfo、MAT
  • 应急与优化:OOM转储、参数与收集器策略、案例化分析

# 1. 进货与入库:类加载 → 元空间/方法区

流程(loadClass):加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载。

  • 加载:按需读取.class字节码,生成java.lang.Class对象(堆中),作为方法区类元数据的访问入口。
  • 验证:字节码合法性/安全性校验。
  • 准备:为静态变量分配内存并赋零值。
  • 解析:符号引用 → 直接引用(静态链接),运行期仍可动态链接。
  • 初始化:执行静态变量赋值与<clinit>静态代码块。

方法区/元空间存放:运行时常量池、类型/字段/方法信息、类加载器引用、对应Class实例引用等。

类加载器与双亲委派:

  • 引导(Bootstrap,C++实现)、扩展(Ext)、应用(App)、自定义(继承ClassLoader,重写findClass)。
  • 双亲委派:先问“父亲”,加载不到再“儿子”。好处:沙箱安全、避免重复加载、保证唯一性。
  • 打破/定制:容器(如Tomcat)为实现“多应用隔离/共享、JSP热加载”等,构建自定义类加载器层次,必要处打破默认委派,但仍尊重JDK核心类的沙箱边界。

示例与要点(摘自 01.JVM类的加载机制):

  • Demo:打印各级类加载器与加载路径;Launcher.getBootstrapClassPath() 列举引导类加载路径。
  • 源码骨架:ClassLoader#loadClass 先 findLoadedClass,再委派父加载器,最顶层失败后回落到子加载器 findClass。
  • Tomcat类加载器体系:commonLoader(容器与各Webapp可见)、catalinaLoader(容器私有)、sharedLoader(Webapp共享)、WebappClassLoader(每war私有,可隔离不同依赖版本与支持JSP热加载)。
  • 打破委派的动机:同一JVM内允许“相同类名+不同类加载器”并存,避免类版本冲突/重复加载,满足应用隔离与热替换。
  • 注意:判断“同一个类”需同时比较“类全名+类加载器实例”。

类卸载(无用类判定):无实例、加载它的ClassLoader可回收、Class对象不可达且不可反射访问。


# 2. 下单与生产:对象创建与执行流水线

对象创建(new)五步:

  1. 加载检查:常量池能定位到类的符号引用,且已加载/解析/初始化,否则先触发类加载流程。
  2. 分配内存(堆):
    • 指针碰撞(默认,堆规整时);空闲列表(堆不规整时)。
    • 并发安全:CAS+失败重试 或 TLAB(每线程本地分配缓冲,-XX:+UseTLAB)。
  3. 零值初始化:为实例字段赋零值(不含对象头)。
  4. 设置对象头:MarkWord(HashCode、年龄、锁状态、偏向线程ID、时间戳等)、Klass Pointer(类元数据指针)、对齐填充。
  5. 执行<init>:按程序员意愿赋值与构造逻辑(区别于零值初始化)。

指针压缩(64位内存占用优化):

  • UseCompressedOops(普通对象指针)、UseCompressedClassPointers(类指针)。堆≤32G场景显著提升对象密度;>32G将失效转为8字节寻址。

逃逸分析与栈上分配:

  • -XX:+DoEscapeAnalysis配合-XX:+EliminateAllocations,将不逃逸的聚合对象拆为标量放入栈帧/寄存器,减少堆分配与GC压力。

执行流水线(字节码/操作数栈):

  • 方法执行创建栈帧(局部变量表、操作数栈、动态链接、返回地址)。
  • 指令示例:iload/istore(变量和栈交互)、invokestatic/invokevirtual(调用)、if_acmpne/goto(跳转)。

字节码观察要点(摘自 10.字节码与操作数栈):

  • stack/locals/args_size:分别代表最大操作数栈深度、局部变量表槽位数、形参数量。
  • LineNumberTable:源代码行号与指令偏移映射;调试/采样分析用。
  • LocalVariableTable:局部变量在字节码生命周期内的作用域、名称与槽位索引。
  • StackMapTable:类型验证与快速校验框架,JDK7开始对ClassFile验证很关键。
  • 自动装箱/缓存示例:Integer.valueOf缓存[-128,127],==对比引用将出现10相等、128不等;Boolean.valueOf仅缓存TRUE/FALSE;Double不缓存一般数值。

对象头与对齐(摘自 03.JVM对象创建与内存分配机制):

  • MarkWord:哈希码、分代年龄、锁状态标志、偏向线程ID、时间戳。
  • Klass Pointer:指向类元数据;压缩类指针启用后由8字节压至4字节。
  • 对齐填充:对象尺寸按8字节对齐以优化寻址与缓存利用。

分配细节与并发安全:

  • 内存划分:指针碰撞(规整堆更快)、空闲列表(非规整堆需维护空闲链)。
  • 并发:CAS失败重试 或 TLAB按线程预配(-XX:+UseTLAB 默认开启,-XX:TLABSize可调)。

指针压缩联动关系(关键结论):

  • 开启UseCompressedOops通常会强制开启UseCompressedClassPointers;若仅开类指针压缩而关Oops会报错(类指针压缩依赖Oops压缩)。
  • 小对象示例:在开启压缩下,引用字段与klass指针从8→4字节,提升堆密度。

示例:栈上分配与逃逸分析压力测试(见 03 文内 AllotOnStack 示例)

  • 关键参数:-Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC
  • 关闭任意一项(逃逸分析或标量替换)将显著增加堆分配与GC次数。

# 3. 成品仓储:堆内存分代与晋升策略

新生代(Eden + From/To Survivor)与老年代:

  • 绝大多数对象“朝生夕死”,Eden满触发Minor GC;幸存对象在S区间来回复制并增长年龄;达到阈值(MaxTenuringThreshold,默认15;CMS常为6)晋升老年代。
  • 动态年龄判断:当某S区内各年龄段对象总和超目标(TargetSurvivorRatio默认50%),≥该最大年龄的对象提前晋升。
  • 大对象:超过-XX:PretenureSizeThreshold(仅Serial/ParNew生效)直接进老年代,避免新生代复制成本。
  • 空间分配担保:Minor GC前评估老年代可用空间与历史晋升均值,必要时触发Full GC以担保复制与晋升安全。

堆大小与代际比例:

  • -Xms/-Xmx堆初始/最大,-Xmn新生代,-XX:NewRatio新老比,-XX:SurvivorRatioS:Eden比(默认8:1:1)。
  • 建议尽量让对象在新生代分配与回收,减少老年代压力与Full GC频率。

引用与可达性:

  • 强/软/弱/虚引用;GC Roots(线程栈、本地方法栈、静态字段等);可达性分析决定存活性。
  • finalize()仅作二次标记的“自救”机会,业务上尽量避免依赖。

GC触发条件(摘自 02.JVM内存模型):

  • Minor GC:Eden满。
  • Full GC:System.gc()建议;老年代空间不足;方法区(元空间)不足;Minor后晋升均值超出老年代可用;复制到To Survivor溢出转入老年代且老年代不足;空间担保失败等。

新生代与S区比例:

  • -XX:NewRatio(例如4→新:老=1:4)、-XX:SurvivorRatio(例如8→(S0+S1):Eden=2:8)。
  • -XX:+UseAdaptiveSizePolicy默认自适应,若需稳定8:1:1可关闭该策略。

# 4. 清洁巡检:GC算法与实现细节

分代收集思想:不同存活特征采用不同算法。

  • 复制(新生代):空间换时间,吞吐高。
  • 标记-清除(老年代):快但有碎片。
  • 标记-整理(老年代):消碎片但更耗时。

并发标记中的三色标记与屏障:

  • 三色:白(未达)、灰(达未扫完)、黑(达且已扫)。
  • 漏标与多标:
    • 增量更新(CMS):写屏障记录“黑→白”新增引用,重标记回扫这些黑对象。
    • SATB(G1/Shenandoah):写屏障记录“灰删除对白”的旧引用,保持起始快照的一致性,重标记回扫。
  • 读屏障(ZGC):通过读屏障配合转发指针解决并发移动中的可见性与一致性。

跨区引用的记忆集/卡表:

  • 避免扫描非收集区全堆,对非收集区维护指向收集区的指针集合;HotSpot以卡表(512B卡页)+写屏障维护“脏卡”。

触发条件精要:

  • Minor GC:Eden满。
  • Full GC:老年代不足/方法区不足/混合回收失败/空间担保失败/显式System.gc()(建议)等。

图片索引(见原文):

  • 分代与算法示意图:http://blogimg.gkmall.top/img/jvm/202305271320740.jpg 等
  • 三色标记、写/读屏障图解:http://blogimg.gkmall.top/img/jvm/202305271323785.jpg 等

# 5. 设备选型:主流垃圾收集器与场景

Serial/Serial Old:单线程,Stop-The-World,简单高效但停顿长。

Parallel/Parallel Old(JDK8默认):多线程吞吐优先,年轻代复制,老年代标整。

ParNew:年轻代并行,常与CMS搭配。

CMS:最短停顿优先(老年代并发标记-清除)。优点:低停顿;缺点:浮动垃圾、碎片、并发失败回退Full GC。关键参数:

  • -XX:+UseConcMarkSweepGC,-XX:CMSInitiatingOccupancyFraction,-XX:+UseCMSInitiatingOccupancyOnly。

G1:面向大堆、可预期停顿,Region化管理,整体标整、局部复制;Young GC/Mixed GC/Full GC三类回收,目标停顿-XX:MaxGCPauseMillis。关键参数:

  • -XX:+UseG1GC、-XX:G1HeapRegionSize、-XX:InitiatingHeapOccupancyPercent、-XX:G1MixedGCLiveThresholdPercent、-XX:G1MixedGCCountTarget、-XX:G1HeapWastePercent、-XX:TargetSurvivorRatio、-XX:MaxTenuringThreshold。

选择建议(经验向):

  • 吞吐优先:Parallel/Parallel Old。
  • 低停顿优先(4~8G):CMS。
  • 大堆与停顿可控(≥8G):G1(或更进阶的ZGC/Shenandoah但JDK版本依赖)。

G1工作流细节(摘自 05.JVM垃圾收集器):

  • Region化堆(1MB~32MB,2的幂,默认2048个分区,-XX:G1HeapRegionSize)。
  • Young GC:并非Eden一满即触发,会结合-XX:MaxGCPauseMillis预算决定何时回收与扩张年轻代。
  • Mixed GC:并发标记后按老年代Region存活率阈值与回收收益选择一批Old Region与Young一起回收;目标次数-XX:G1MixedGCCountTarget;阈值-XX:G1MixedGCLiveThresholdPercent。
  • Full GC:复制失败或空Region不足时退化为单线程压缩(JDK更高版本有并行化改进)。
  • 关键触发/控制:
    • -XX:InitiatingHeapOccupancyPercent(并发标记的全堆占用率阈值,默认45%)。
    • -XX:G1HeapWastePercent(回收过程中“空出来的Region”达到堆的该比例即停止本轮混合回收,默认5%)。
    • -XX:TargetSurvivorRatio/-XX:MaxTenuringThreshold 影响晋升节奏与S区承载。

CMS阶段与注意点(摘自 05.JVM垃圾收集器):

  • 阶段:初始标记(STW,标记GC Roots直接可达对象)→ 并发标记(与应用并发,三色标记)→ 重新标记(STW,增量更新回扫)→ 并发清理(清除未标记对象)→ 并发重置。
  • 特点:低停顿但会产生浮动垃圾(并发期间新垃圾留到下轮);基于标记-清除会有碎片;并发失败将退化为STW Full GC。
  • 关键参数:-XX:+UseConcMarkSweepGC、-XX:CMSInitiatingOccupancyFraction=<阈值>、-XX:+UseCMSInitiatingOccupancyOnly。

# 6. 仪表盘与运维:参数、日志与工具

常用内存/代际参数(示例以JDK8为主):

  • 线程栈-Xss;堆-Xms/-Xmx/-Xmn;新老比例-XX:NewRatio;S区比例-XX:SurvivorRatio。
  • 元空间:-XX:MetaspaceSize(初始触发Full GC阈值,默认约21M,建议与-XX:MaxMetaspaceSize设一致且略大于默认阈值,如256M),-XX:MaxMetaspaceSize。
  • OOM转储:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=...。
  • 容器化:-XX:+UseContainerSupport -XX:MaxRAMPercentage=<x> -XX:InitialRAMPercentage=<x> -XX:MinRAMPercentage=<x>。
  • G1目标停顿:-XX:MaxGCPauseMillis(过小会混合回收跟不上,易Full GC)。

容器化与一体化示例命令(摘自 06.JVM调优工具以及调优实战):

java -XX:+UseContainerSupport \
     -XX:MaxRAMPercentage=60.0 -XX:InitialRAMPercentage=60.0 -XX:MinRAMPercentage=60.0 \
     -XX:NewRatio=2 -Xss512k \
     -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M \
     -Djava.awt.headless=true -d64 -server -Djava.net.preferIPv4Stack=true \
     -Djavax.servlet.request.encoding=UTF-8 -Dfile.encoding=UTF-8 \
     -XX:+AlwaysPreTouch \
     -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly \
     -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps \
     -jar app.jar
1
2
3
4
5
6
7
8
9
10
  • 每个参数的意义见 06 文详细注释;建议按物理/容器限额设置RAM百分比,Metaspace初始与最大设置一致并高于21M默认触发阈值。

常用jstat指标(节选自 06 文):

  • -gc:S0C/S1C/S0U/S1U、EC/EU、OC/OU、MC/MU、CCSC/CCSU、YGC/YGCT、FGC/FGCT、GCT。
  • -gccapacity:新生代/老年代/元空间的最小、最大、当前容量。
  • -gcnew/-gcnewcapacity:新生代对象年龄阈值(TT/MTT)、期望幸存区大小(DSS)等。
  • -gcold/-gcoldcapacity:老年代容量与回收统计。
  • -gcmetacapacity:元空间/压缩类空间容量与使用。

jstat字段释义补充(整合 06 文):

  • -gc:
    • S0C/S1C:两个Survivor区容量(KB);S0U/S1U:各自使用量;
    • EC/EU:Eden容量/使用量;OC/OU:Old容量/使用量;
    • MC/MU:Metaspace容量/使用;CCSC/CCSU:压缩类空间容量/使用;
    • YGC/YGCT:Young GC次数/耗时(s);FGC/FGCT:Full GC次数/耗时(s);GCT:GC总耗时(s)。
  • -gccapacity:
    • NGCMN/NGCMX/NGC:新生代最小/最大/当前;S0C/S1C/EC 同上;
    • OGCMN/OGCMX/OGC/OC:老年代最小/最大/当前/当前(容量口径不同);
    • MCMN/MCMX/MC:元空间最小/最大/当前;
    • CCSMN/CCSMX/CCSC:压缩类空间最小/最大/当前;
    • YGC/FGC:次数。
  • -gcnew:
    • S0C/S1C/S0U/S1U、EC/EU 同上;
    • TT/MTT:当前提升到老年代的年龄阈值/最大阈值;DSS:期望幸存区大小。
  • -gcnewcapacity:
    • NGCMN/NGCMX/NGC:新生代容量边界与当前;
    • S0CMX/S0C、S1CMX/S1C:两个S区最大/当前容量;ECMX/EC:Eden最大/当前容量;
    • YGC/FGC:次数。
  • -gcold/-gcoldcapacity:
    • OC/OU:老年代容量/使用量;FGCT/GCT:耗时统计等。
  • -gcmetacapacity:
    • MCMN/MCMX/MC:元空间;CCSMN/CCSMX/CCSC:压缩类空间;YGC/FGC/FGCT/GCT 同上。

常用jmap/jstack/jinfo:

  • jmap -histo <pid>:类实例数与占用;-heap堆布局;-dump:format=b,file=...导出dump。
  • jstack <pid>:线程栈/死锁/高CPU线程定位(结合top -Hp与16进制TID)。
  • jinfo -flags/-sysprops <pid>:查看JVM参数与系统属性,部分参数可运行时调整。

GC日志判读(示例在11.GCLog分析.md):

  • 关注Young区变化、堆整体变化、晋升量=Young清理量-堆整体释放量;频繁Full GC通常意味着老年代顶不住或空间担保失败。

命令行工具(06.JVM调优工具以及调优实战.md):

  • jps(进程)、jmap(heap直方图/堆信息/导出dump)、jstack(线程栈/死锁/高CPU线程定位)、jinfo(参数/部分运行时可调)、jstat(各区使用量与GC统计,如jstat -gc/-gccapacity/-gcnew/-gcold/-gcmetacapacity)。

GC日志开关与输出:

  • JDK8常用:-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:<file>;
  • JDK9+统一日志:-Xlog:gc*,safepoint:file=<file>:tags,uptime,time,level;
  • 生产建议:固定日志文件路径并轮转,结合可视化工具(如 GC Easy)辅助判读。

高CPU线程定位步骤(整合 06 文):

  • top -Hp <pid>查看线程占用;记下最高TID;
  • 将TID转16进制(如Linux printf "%x\n" <tid>);
  • jstack <pid> | grep -A 30 <hexTid>定位堆栈热点方法;
  • 结合业务日志/监控比对确认异常热点。

MAT离线分析(详见40.JVM 内存分析工具 MAT及实践.md):

  • 核心视图:Dominator Tree(支配内存/Retained Heap)、Histogram(类直方图)、Leak Suspects(疑似泄漏)、Path to GC Roots(强引用链)、Thread Overview(线程与持有对象)、Class Loader Explorer(类加载器与重复类)。
  • 常见排查切入:
    • 先看Dominator Tree定位“谁支配了大头内存”,再结合Histogram做聚合;
    • Path to GC Roots溯源“为何不可回收”;
    • Class Loader Explorer定位“过多ClassLoader/重复类版本冲突”;
    • Collections工具看ArrayList填充率/HashMap冲突;
  • OQL按业务条件批量筛选、导出做进一步分析。

MAT关键步骤与案例摘记(节选整合 40 文):

  • Heap Dump Overview:先扫全局(对象数、ClassLoader数、GC Roots数、线程概况)。
  • Dominator Tree:Top1常用入口,按package/class/classloader聚类,直击“谁在支配谁”;右键“Immediate Dominator”溯源直接支配者。
  • Histogram:Top2常用入口,计算Retained Heap后排序,结合正则与分组快速锁定大头类。
  • Leak Suspects:自动探测疑似泄漏点,适用于快速入手。
  • Thread Overview:看线程持有对象与阻塞栈,命名规范可极大提升定位效率。
  • Path To GC Roots:建议勾选“exclude all phantom/weak/soft”,聚焦强引用链。
  • Class Loader Explorer / Duplicated Classes:定位ClassLoader风暴与重复类版本。
  • Collections:查看ArrayList填充率、HashMap冲突,找出“占坑不放货”的空/稀疏集合。
  • OQL:SELECT * FROM WHERE ;例如:select * from java.util.ArrayList where size=0 and modCount=0快速找空表对象;可将结果导出再做脚本分析。

# 7. 事故与优化:应急流程与调优要点

应急流程(堆飙升/频繁Full GC/OOM):

  • 开启GC日志与HeapDump(若未开,复现前先配置);
  • 通过jstat -gc观察Young/Old压力、YGC/FGC次数与耗时;
  • jmap -histo看对象分布大头;必要时导出jmap -dump→MAT定位支配对象与引用链;
  • jstack定位可疑线程(高CPU/死锁/阻塞导致对象长时间存活)。

常见优化抓手:

  • 让对象尽量在新生代“就地去世”,减小晋升与老年代压力;
  • 合理设置堆/新生代大小、目标停顿时间,避免Survivor放不下触发“动态年龄判定”过早晋升;
  • 大对象直配老年代仅在确有必要时启用;
  • CMS场景关注碎片与并发失败,必要时压缩或转向G1;
  • G1关注MaxGCPauseMillis、InitiatingHeapOccupancyPercent、G1MixedGCCountTarget等参数的均衡;
  • 元空间大小与触发阈值尽量一致、略高于默认以避免频繁Full GC的“抖动”。

GC日志样例要点(整合 11.GCLog分析):

  • 示例行:[PSYoungGen: 16384K->2016K(18432K)] 16384K->14294K(59392K)
    • 年轻代释放:16384-2016=14368K;堆总释放:16384-14294=2090K;
    • 晋升近似:14368K-2090K≈12278K(清理的年轻代-堆整体释放 ≈ 进入老年代)。
  • 关注频繁Full GC:多由老年代压力/晋升过快/空间担保失败导致。

KPI观念:

  • 吞吐量(总运行时间中GC占比越低越好)
  • 最大停顿(客户端/延迟敏感优先)
  • 内存占用(容器化/成本敏感)

# 8. 工厂隐喻一览(快速映射)

  • 原料进货 → 类加载(到元空间)
  • 入库上架/打标 → 验证/准备/解析/初始化
  • 原料仓 → 元空间/方法区
  • 运输/物流 → 类加载器/双亲委派/沙箱
  • 订单下发 → new对象/方法调用
  • 车间与工艺 → 执行引擎/方法栈/操作数栈/字节码
  • 质检与贴标 → 零值初始化/对象头(MarkWord、Klass Pointer、对齐)
  • 成品区 → 堆(Eden/Survivor/Old、晋升/大对象)
  • 客户标记 → 引用类型与可达性(GC Roots)
  • 清洁巡检 → GC算法(复制/标清/标整)、三色标记/屏障、记忆集/卡表
  • 设备与产线 → 收集器(Serial/Parallel/ParNew/CMS/G1)
  • 仪表与报警 → 启动参数/GC日志/jstat/jmap/jstack/jinfo/MAT
  • 故障与应急 → OOM转储、GC调优与案例分析

# 9. 参考与延伸

  • 源笔记详见当前目录各.md文件;其中:
    • 类加载与双亲委派:01.JVM类的加载机制.md
    • 内存模型与参数:02.JVM内存模型.md
    • 对象创建/分配/晋升/引用:03.JVM对象创建与内存分配机制.md
    • GC算法与三色标记/屏障/卡表:04.JVM垃圾收集算法.md
    • 收集器与G1参数:05.JVM垃圾收集器.md
    • 启动参数与运维工具:06.JVM调优工具以及调优实战.md
    • 字节码/操作数栈:10.字节码与操作数栈.md
    • GC日志解析:11.GCLog分析.md
    • MAT实战:40.JVM 内存分析工具 MAT及实践.md

以上内容按“工厂”主线串联,便于整体理解与实战定位。若需要,我可以基于你的运行环境与业务负载,补充“场景化参数模板”和“调优分步剧本”。


# 附录A 参数清单精选(整合 02/05/06)

  • 内存与分代
    • -Xss<size>:每线程栈大小(经验值3000~5000线程范围要平衡)。
    • -Xms/-Xmx:堆初始/最大;-Xmn:新生代大小。
    • -XX:NewSize/-XX:MaxNewSize:新生代初始/最大容量。
    • -XX:OldSize:老年代大小(较少直接设,通常通过整体与新生代推导)。
    • -XX:NewRatio=<n>:新:老=1:n(例4→1:4)。
    • -XX:SurvivorRatio=<n>: (S0+S1):Eden=2:n(例8→2:8)。
  • 元空间/类指针
    • -XX:MetaspaceSize=<m>:初始阈值(默认约21M,触发Full GC做类型卸载与阈值自调)。
    • -XX:MaxMetaspaceSize=<m>:最大元空间,建议与初始设为一致且略高于默认触发阈值(如256M)。
    • -XX:+UseCompressedOops、-XX:+UseCompressedClassPointers:64位堆≤32G建议开启(一般默认开)。
  • 收集器选择
    • -XX:+UseParallelGC、-XX:+UseParallelOldGC:吞吐优先;JDK8默认。
    • -XX:+UseConcMarkSweepGC:CMS老年代;-XX:CMSInitiatingOccupancyFraction=<%>、-XX:+UseCMSInitiatingOccupancyOnly。
    • -XX:+UseG1GC:大堆/可预测停顿;-XX:MaxGCPauseMillis=<ms>、-XX:InitiatingHeapOccupancyPercent=<%>、-XX:G1HeapRegionSize=<size>、-XX:G1MixedGCLiveThresholdPercent=<%>、-XX:G1MixedGCCountTarget=<n>、-XX:G1HeapWastePercent=<%>、-XX:TargetSurvivorRatio=<%>、-XX:MaxTenuringThreshold=<n>、-XX:ConcGCThreads=<n>、-XX:G1OldCSetRegionThresholdPercent=<%>。
  • 其他关键项
    • -XX:+AlwaysPreTouch:启动时预触摸堆以避免运行时缺页。
    • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path>:OOM生成dump与路径。
    • GC日志:JDK8 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:<file>;JDK9+ -Xlog:gc*。
    • 容器:-XX:+UseContainerSupport -XX:MaxRAMPercentage=<x> -XX:InitialRAMPercentage=<x> -XX:MinRAMPercentage=<x>。

# 附录B MAT综合案例简版(整合 40)

  • 案例1(ClassLoader风暴/大集合持有)
    • 代码要点:循环创建自定义ClassLoader加载同名类;两个线程睡眠并间接持有一个巨大的ArrayList<Integer>。
    • 路线:
      • Heap Dump Overview → 发现ClassLoader数异常、线程数/名称;
      • Class Loader Explorer → 聚合定位自定义Loader;
      • Dominator Tree(聚合到class)→ 找到支配内存的大类/容器;
      • Path to GC Roots / incoming references → 回溯到具体创建路径;
      • Collections → 验证大集合具体装载量与空间浪费。
  • 案例2(NoClassDefFoundError/重复类)
    • 路线:Java Basics → Duplicated Classes → 过滤类名 → Inspector 查看类来源jar/war → 清理冲突版本/Loader配置。
  • 案例3(大量空ArrayList占用)
    • OQL:select * from java.util.ArrayList where size=0 and modCount=0 → Histogram计算Retained Heap总量 → incoming references定位来源 → 设计懒加载或延迟初始化。

# 附录C 常见调优剧本(从症状出发)

  • 症状:FGC频繁、老年代接近满
    • 看:jstat -gc的OU/FGC/FGCT;GC日志FGC原因;
    • 做:增大堆或降低晋升速率(增大S区、调整MaxTenuringThreshold、合理TargetSurvivorRatio);评估大对象直配策略;必要时从CMS切到G1。
  • 症状:YGC很频繁、单次停顿短但整体抖动
    • 看:Eden大小与对象分配速率;
    • 做:适度扩大新生代或放宽MaxGCPauseMillis目标(G1),避免过窄导致频繁Young GC。
  • 症状:Metaspace触发Full GC抖动
    • 做:将MetaspaceSize≈MaxMetaspaceSize并高于21M默认阈值;排查频繁生成/卸载的动态类(代理/JSP)。
  • 症状:高CPU热点线程
    • 路线:top -Hp→十六进制TID→jstack | grep -A → 找热点堆栈;对代码与依赖做热点优化/限流/降级。
上次更新: 2025/10/14, 19:04:49
JVM 内存分析工具 MAT及实践
Oracle:JVM & G1垃圾收集器

← JVM 内存分析工具 MAT及实践 Oracle:JVM & G1垃圾收集器→

最近更新
01
提示词工程实践指南
10-19
02
chatGpt提示原则
10-19
03
AI是如何学习的
10-19
更多文章>
| Copyright © 2022-2025 Kevin | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式