JVM虚拟机技术是什么,如何学习?

JVM虚拟机技术是Java应用稳定运行的基石,掌握其内存模型与调优方法,是解决线上性能问题和通过大厂面试的核心能力。

JVM(Java Virtual Machine)是一门“看着抽象、用着具体”的技术,很多开发者在写代码时感觉不到它的存在,但一旦遇到线上CPU飙升、接口频繁卡顿、系统频繁Full GC,才会意识到JVM知识储备的重要性,下文从内存结构、垃圾回收器选择、调优操作、故障排查四个维度展开,全程用实操逻辑说话。

先弄懂JVM的内存到底怎么划分

很多人背过JVM内存模型,但真正遇到问题还是不知道看哪里,行业共识认为,JVM内存分区就是一套“对象生产车间”的流水线布局,理解它,不需要啃晦涩的规范文档,只需要搞懂每个区域“装什么、满了会怎样、谁负责清理”。

堆内存是主角,也是故障高发地

堆是JVM管理的最大一块内存,几乎所有对象实例都在这里分配,堆内部又细分为新生代和老年代,其中新生代还分为Eden区、From Survivor区和To Survivor区。

  • 新生代:大部分短命对象在这里出生,Minor GC(新生代垃圾回收)会频繁在这里工作。
  • 老年代:挺过多轮Minor GC的“长寿对象”会晋升到这里,Major GC或Full GC主要清理这里。
  • 元空间(Metaspace):存储类元数据信息,取代了JDK8之前的永久代,它使用的是本地内存,默认情况下大小不受JVM堆内存限制。

接口报错 OutOfMemoryError: Java heap space 就是堆内存耗尽,最常见的原因是某个集合类无限增长,或者一次查询加载的数据量远超预期。

虚拟机栈与本地方法栈:线程的私有空间

每个线程创建时都会分配一个虚拟机栈,里面存放一个个栈帧,每个方法调用对应一个栈帧,栈帧里保存了局部变量表、操作数栈、动态链接和方法出口等信息,线程请求的栈深度超过最大值时,会抛出 StackOverflowError,常见于无限递归。

程序计数器:最小的内存区域

程序计数器是当前线程所执行字节码的行号指示器,它占用空间极小,且是JVM规范中唯一没有规定OutOfMemoryError情况的区域。

垃圾回收器选型:G1和CMS垃圾回收器对比

JVM提供多种垃圾回收器,选择逻辑不是“哪个新用哪个”,而是“哪个匹配自己的业务延迟诉求”,目前JDK11及更高版本中,G1已经是默认收集器,但在低延迟场景下,ZGC正在快速普及。

G1和CMS的核心差异

G1的设计目标是“在可预测的停顿时间内,尽量完成垃圾回收”,它把堆划分为多个大小相等的Region区域,通过维护一个优先级列表,优先回收价值最大的Region,CMS(Concurrent Mark Sweep)则是以“最短回收停顿时间”为目标的并发收集器,但它在JDK9后被标记为废弃。

JVM虚拟机技术是什么,如何学习?

对比维度

G1收集器CMS收集器
内存布局基于Region分区,逻辑分代物理分代,连续内存
回收算法复制算法+标记整理标记清除
停顿预测支持可预测停顿时间模型依赖并发线程,无法精确预测
碎片问题基本无碎片,Region间复制内存碎片较多,大对象分配受影响
适用场景堆内存较大(6GB以上)、多核CPUJDK8及以前、追求低停顿的小内存应用

CMS已经进入维护期,业内专家指出,还在用JDK8且堆内存超过8GB的场景,优先迁移到G1是比较理性的选择,迁移的成本主要在JVM参数调整,业务代码几乎不需要改动。

怎么判断当前使用的是哪个垃圾回收器

执行以下命令可以快速查看Java进程使用的收集器组合:

jcmd <pid> VM.flags | grep -i "UseG1GC|UseCMS|UseZGC"

JDK8默认使用ParallelGC(并行收集器),JDK11及以上默认启用G1,如果线上堆内存较大且频繁看到“Pause Full (Allocation Failure)”日志,说明GC压力已经很大,单纯调整堆大小已经不够,需要考虑更换收集器参数。

JVM调优参数怎么设置:别乱加,按场景来

JVM调优不是把网上流传的参数堆上去就行,参数之间讲究配合,调优的核心目标只有两个:一是降低Full GC频率,二是减少单次GC停顿时间,实际生产环境里,这两者往往是矛盾的,需要权衡。

堆内存大小设置策略

推荐使用 -Xms-Xmx 设置相同值,避免堆大小在运行期动态伸缩带来的性能损耗,多数情况下,堆大小设置为系统物理内存的50%-70%比较合理,剩余内存留给操作系统缓存和元空间。

具体操作时,在启动脚本中加入:

java -Xms4g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar your-service.jar

上面的参数含义是:堆初始和最大均为4GB,使用G1收集器,目标停顿时间200毫秒,需要额外说明的是,MaxGCPauseMillis只是软目标,G1会尽力达成,不保证绝对精确。

元空间与线程栈的调整

对于频繁加载或动态生成类的应用(如Spring Boot、MyBatis、CGLIB代理),建议显式设置元空间上限,防止元数据泄漏拖垮系统:

-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m

线程栈大小使用默认值即可,除非有明确的递归深度需求,否则不建议修改 -Xss 参数,修改不当会直接导致线程创建失败。

JVM内存溢出怎么排查:从现象到根因

线上出现内存溢出,第一反应不能是重启,而是要留下现场证据,完整的排查链路分为四步:拿到堆转储文件、分析对象分布、定位代码位置、验证修复效果。

JVM虚拟机技术是什么,如何学习?

第一步:保留故障现场

启动参数里加上自动导出堆转储的配置:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/heapdump.hprof

这样JVM在抛出内存溢出错误时,会自动生成堆转储快照文件,如果没有加这个参数,可以用 jmap 手动导出,但操作需要谨慎,导出过程会暂停应用:

jmap -dump:format=b,file=/data/logs/heapdump-20260615.hprof <pid>

第二步:用MAT分析堆转储文件

打开Eclipse MAT(Memory Analyzer Tool),选择“Leak Suspects Report”,工具会自动找出最可疑的持有大对象的线程和对象,重点看三处:

  • Dominator Tree(支配树):找出占用堆内存最大的对象及其引用链。
  • Thread Details:查看哪个线程的栈帧中持有了大量对象。
  • 重复对象检测:排查是否存在同一个大对象被多份拷贝。

开发环境里排查JVM内存溢出,可以先用MAT这样的可视化工具定位问题类。

第三步:修复与验证

分析完成后,修复方向通常是内存泄漏或并发流量高峰的问题,一个批量导出功能将查询结果全部放入内存后再写文件,换成流式查询(使用游标方式每次取固定行数)即可解决。

验证修复效果时,建议压测环境模拟线上峰值流量,测试前记录Full GC频率和平均停顿时间,测试后对比数据。

JVM面试题及答案:这些考点经常被问

JVM是Java面试的必考板块,面试官不会直接问“什么是JVM”,而是从实战视角切入,以下三个问题属于高频中的高频。

解释一下JVM的类加载过程?

类加载分为加载、链接、初始化三个阶段,链接又细分为验证、准备、解析,加载阶段通过类的全限定名获取二进制字节流;验证阶段确保字节流符合JVM规范;准备阶段为静态变量分配内存并赋零值;解析阶段将符号引用替换为直接引用;初始化阶段执行静态代码块和赋值操作。

Full GC频繁怎么办?

优先用 jstat -gcutil 1000 观察各内存区域的变化趋势,如果老年代稳定增长且每次Full GC后回收效果不明显,基本判定为内存泄漏,如果老年代占用率居高不下但回收后有效,说明存活对象过多或堆容量偏小,前者需要代码层修复,后者需要调整堆大小或更换收集器。

什么是STW(Stop The World)?

STW是指垃圾回收过程中,JVM暂停所有业务线程的现象,几乎所有垃圾回收算法都会经历STW,只是停顿时长不同,G1通过并发标记和可预测停顿模型,尽量压缩STW时间,ZGC的STW时间则可以控制在1毫秒以内,支撑了TB级堆内存的应用场景。

JVM线上故障排查的常规武器

排查JVM问题需要依靠工具链,这些命令不一定每天用,但关键时刻能救命。

JVM虚拟机技术是什么,如何学习?

  • jps:列出当前机器上的Java进程,拿到PID。
  • jstat:监视JVM内存、GC、类加载的统计信息。
  • jstack:导出线程快照,排查死锁、线程阻塞、热点方法。
  • jmap:导出自定义堆转储文件,查看堆内存概要。
  • jcmd:JDK8及以上版本的整合工具,集合了多项VM操作功能。

举个例子,线上应用CPU飙到100%时,先用top定位进程PID,再执行top -Hp <pid>找到CPU占用最高的线程ID,将其转换为16进制后,用jstack <pid> | grep <十六进制线程ID>就能精确锁定对应的业务代码位置,这个排查链路是每一个Java服务端工程师的基本功。

JVM和Docker容器共存时的内存边界

现代部署模式普遍采用容器化,JVM在容器内的行为值得关注,运行在Docker环境下的Java应用,如果未显式设置堆大小,JVM可能识别不到容器内存上限,而是直接读取宿主机的CPU核数与内存大小,造成容器被系统Kill,解决办法是在启动命令中显式设置-Xmx,或者使用-XX:+UseContainerSupport(JDK10及以上默认开启)并结合-XX:MaxRAMPercentage来按比例分配:

java -XX:MaxRAMPercentage=70.0 -jar your-app.jar

这种方式让JVM自动感知容器内存限制,按比例分配堆内存,比硬编码堆大小更适配弹性伸缩的容器环境。

JVM常见问题

JVM调优参数怎么设置才能减少Full GC次数?

减少Full GC的根本是控制老年代对象的晋升速率,具体操作包括:调大新生代空间比例(比如-XX:SurvivorRatio=6),延长对象在新生代的存活时间;避免在循环中创建大对象;排查是否存在集合类持有无效引用,参数调整只是辅助手段,代码层面的对象生命周期管理才是根本解法。

G1收集器的Region大小怎么计算?

G1的Region大小由JVM根据堆内存自动推算,最小1MB,最大32MB,必须是2的幂次,当堆大小为4GB时,Region通常为2MB,不建议手动指定-XX:G1HeapRegionSize,让JVM按默认规则计算更可靠,手动指定不当会造成Region数量过多或过少,影响回收效率。

元空间内存溢出和堆内存溢出有什么本质区别?

堆内存溢出是对象实例过多导致的,元空间溢出是类元数据过多导致的,堆溢出多见于业务代码问题,元空间溢出常见于大量动态代理类生成、热部署场景未清理类加载器,排查元空间溢出时,关注点不在对象数量,而在于类加载器是否被正确卸载。

JVM虚拟机技术的学习路径不需要贪多求全,先把内存模型、垃圾回收、故障排查这三件事打通,再按需深入调优参数底层原理,真正理解JVM的开发者,拿到任何一台线上Java服务都能迅速定位问题,这份能力比记住任何参数都有价值。

首发原创文章,作者:王坚‌,如若转载,请注明出处:https://idctop.com/article/654695.html

(0)
海康威视域名怎么注册,注册费用和流程是什么?
上一篇 2026年9月15日 10:52
政企合规整改中高防到底多重要,高防产品怎么选?
下一篇 2026年9月15日 10:52

相关推荐

  • 个人短信服务怎么申请?个人短信群发平台哪家正规

    个人短信服务并非传统意义上的“群发工具”,而是基于运营商网关接口,面向个人用户或小微团队提供的低成本、高触达的消息通知与互动渠道,适合验证码、提醒及轻量级营销场景,很多人对“个人短信服务”存在误解,认为它是企业专属的营销利器,或者觉得它等同于垃圾短信,随着通信技术的演进,个人短信服务已经分化出不同的应用场景,对……

    2026年5月26日
    4000
  • 佛山做网站公司排名哪家好?,哪家更靠谱?

    佛山做网站公司排名并非单一榜单所能概括,真正决定服务商价值的核心在于技术匹配度、本地化服务能力以及售后响应机制,企业主在选择时,务必根据自身业务阶段、预算范围以及功能需求,锁定最适合的建站伙伴,而非机械追求所谓“第一名”,佛山做网站公司排名核心评估维度排名背后是多个维度的综合博弈,只有拆解出关键指标,才能避免被……

    2026年7月18日
    900
  • 服务器怎么开445端口?Windows和Linux系统开启方法详解

    开启服务器的465端口,核心在于防火墙策略配置与邮件服务监听设置的双重保障,仅开放防火墙而不配置服务监听,或仅修改配置文件而不放行端口,均无法实现SMTPS(SMTP over SSL)的正常通信,必须确保系统防火墙、云服务商安全组以及邮件服务配置文件三者同步设置,才能彻底打通465端口的数据链路, 465端口……

    2026年3月19日
    12900
  • 小孩玩的服务器有哪些推荐?适合儿童的怎么选?

    小孩玩得最多的游戏服务器集中在《我的世界》中国版、Roblox官方服和迷你世界联机大厅,其中以《我的世界》中国版的花雨庭、梦世界等网络服务器最受6-14岁孩子欢迎,这些服务器之所以能成为主流选择,核心原因在于它们提供了家长可控的联机环境、内置的社交过滤机制,以及无需自行搭建的便捷入口,选择适合孩子的服务器,本质……

    2026年8月29日
    1100
  • 常用的web服务器软件有哪些,哪个最稳定?

    常用的Web服务器软件主要包括Apache、Nginx、IIS、Lighttpd和Tomcat,其中Nginx凭借高并发处理能力与Apache的模块化生态长期占据市场绝大多数份额,Lighttpd和Tomcat则在特定场景(如资源受限环境或Java应用)中扮演关键角色,主流Web服务器软件的核心特性与适用场景A……

    2026年8月7日
    600
  • 个人服务器双11怎么买最划算?云服务器选购避坑指南

    2026年个人服务器双11促销的最佳购买时机是11月10日晚8点至11月11日24点,此时主流云厂商通常提供全年最低折扣,建议优先选择按量付费转包年包月以锁定低价,双11期间个人服务器价格波动规律与选购策略对于个人开发者、独立博主以及小型创业团队而言,服务器成本往往是项目初期最大的隐性支出,2026年的云计算市……

    2026年5月29日
    5300
  • 规则引擎sql跑批怎么配置?sql跑批任务调度优化

    规则引擎通过SQL跑批实现批量决策,核心在于将业务逻辑转化为可执行的SQL脚本,利用数据库底层计算能力替代应用层循环,从而大幅提升处理效率并降低系统耦合度,在数字化转型的深水区,企业面对的海量交易数据和实时风控需求,传统的Java或Python代码逐条处理已经显得力不从心,规则引擎SQL跑批方案应运而生,它不仅……

    2026年7月7日
    11700
  • 个人接做网站多少钱?网站定制开发费用一般多少

    个人接做网站的费用通常在3000元到2万元之间,具体价格取决于功能复杂度、技术栈选择以及开发者的经验水平,简单的展示型网站几千元即可搞定,而涉及复杂交互或定制开发的项目则需更高预算,在2026年的数字商业环境中,网站建设早已不再是少数技术人员的专属领域,而是每个企业主必须掌握的生存技能,许多人在寻找个人开发者时……

    2026年5月31日
    6700
  • Python取模运算%怎么用?python取余数怎么算

    在 Python 中, 是取模运算符(Modulo Operator),也称为求余运算符,它用于计算两个数相除后的余数,基本语法result = a % ba 是被除数b 是除数result 是余数基本用法示例print(10 % 3) # 输出: 1 (因为 10 = 3 * 3 + 1)print(10……

    2026年7月11日
    15700
  • 服务器开机u盘启动不起来怎么办,BIOS设置U盘启动教程

    服务器无法通过U盘引导启动,核心原因通常集中在启动盘制作不规范、BIOS引导模式配置错误、USB接口硬件兼容性或U盘本身物理故障这四个维度,解决该问题必须遵循“先软后硬、先配置后物理”的排查逻辑,优先检查BIOS设置中的UEFI/Legacy模式匹配情况,其次验证启动盘的引导文件完整性,最后排查服务器硬件接口与……

    2026年3月27日
    13200

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注