为了账号安全,请及时绑定邮箱和手机立即绑定

JVM入门:核心参数与垃圾回收算法,小白也能看懂

标签:
Java 算法 JVM

作为Java开发者,你可能经常听到“JVM调优”“垃圾回收”这些词,但又觉得它们高深难懂。其实JVM并没有那么神秘——它就像Java程序的“运行管家”,负责管理内存、回收垃圾,而JVM参数是我们给这个“管家”的指令,垃圾回收算法则是它清理内存的“工作方法”。

本文会用最通俗的语言,拆解JVM的核心参数和垃圾回收算法,全程避开复杂术语,保证Java小白也能看懂。

一、先搞懂:JVM为什么需要参数?

Java程序运行时,JVM会默认分配内存、选择垃圾回收方式,但默认配置往往适配不了所有场景:

  • 比如写一个简单的桌面程序,默认内存足够用;但跑一个高并发的电商系统,默认内存可能不够,导致程序卡顿甚至崩溃。
  • JVM参数就是用来“定制”JVM的运行规则——比如告诉它“最多能用多少内存”“用哪种方式回收垃圾”,让程序跑得更顺畅。

二、JVM常用核心参数(小白必懂版)

JVM参数有固定格式,开头一般是-X-XX,我们不用记所有参数,掌握以下10个核心的,就能应对80%的场景。

1. 内存分配类(最常用!)

这类参数用来规定JVM的内存大小,就像给“管家”划定工作空间。

参数 作用(通俗版) 举例
-Xms 给JVM分配的初始内存(启动时就给这么多) -Xms512m:启动时分配512MB内存
-Xmx 给JVM分配的最大内存(最多能用到这么多) -Xmx1024m:最多能用1GB内存
-Xmn 年轻代内存大小(后面讲垃圾回收会用到) -Xmn256m:年轻代分配256MB
-Xss 每个线程的栈内存大小(线程专属空间) -Xss1m:每个线程分配1MB栈内存

小白提醒:

  • m代表MB,g代表GB,比如-Xmx2g就是最大内存2GB;
  • 生产环境中,建议把-Xms-Xmx设为相同值(比如都设为2g),避免JVM频繁调整内存大小导致卡顿;
  • 不要把-Xmx设得太大(比如超过物理机内存的80%),否则会和操作系统抢内存,导致程序变慢。

2. 垃圾回收器类(指定“清理垃圾的方式”)

这类参数用来告诉JVM用哪种算法回收垃圾,不同算法适合不同场景。

参数 作用(通俗版) 适用场景
-XX:+UseSerialGC 使用“串行垃圾回收器”(单线程清理) 简单小程序、单机应用(比如桌面工具)
-XX:+UseParallelGC 使用“并行垃圾回收器”(多线程清理) 后台服务、数据处理(追求高吞吐量)
-XX:+UseConcMarkSweepGC 使用“CMS回收器”(并发清理,少卡顿) 电商、支付系统(追求低延迟)
-XX:+UseG1GC 使用“G1回收器”(平衡吞吐量和延迟) 大部分生产环境(JDK8及以上推荐)

小白提醒:

  • JDK8默认用ParallelGC,JDK9及以上默认用G1GC;
  • 不用纠结“哪个最好”,记住:简单程序用Serial,追求快用Parallel,怕卡顿用G1。

3. 辅助调试类(排查问题用)

这类参数用来让JVM输出运行日志,方便我们排查内存泄漏、卡顿等问题。

参数 作用(通俗版) 举例
-XX:+PrintGCDetails 打印垃圾回收的详细日志(比如什么时候回收、回收了多少) 配合程序运行,输出GC日志文件
-XX:+HeapDumpOnOutOfMemoryError 当JVM内存溢出时,自动生成内存快照文件 排查“OOM(内存溢出)”问题的关键
-XX:HeapDumpPath 指定内存快照文件的保存路径 -XX:HeapDumpPath=/tmp/heapdump.hprof

小白提醒:

  • 开发和测试环境建议开启这些参数,生产环境按需开启(会略增加性能开销);
  • 内存快照文件可以用MAT、JProfiler等工具打开分析。

三、JVM垃圾回收算法(小白也能理解的比喻)

先明确一个核心问题:什么是垃圾?
简单说,就是Java程序运行过程中,不再被使用的对象(比如一个用完的变量、关闭的连接),这些对象占用的内存如果不清理,会越积越多,最终导致内存溢出(OOM)。

垃圾回收算法,就是JVM清理这些“垃圾”的具体方法。我们用“宿舍打扫卫生”来比喻,轻松理解4种核心算法。

1. 标记-清除算法(最基础的“扫垃圾”方式)

核心逻辑(比喻版):

  • 第一步(标记):宿管阿姨逐个检查宿舍,把没人用的物品(垃圾)贴上标签;
  • 第二步(清除):阿姨把贴了标签的物品扔掉。

优点:

逻辑最简单,容易实现;

缺点:

  • 效率低:检查+清理都是单线程,慢;
  • 产生内存碎片:就像宿舍里扔了一堆东西,剩下的空间是零散的,想放个大衣柜(大对象)都放不下。

应用场景:

几乎不单独使用,是其他算法的基础。

2. 复制算法(“分区打扫”更高效)

核心逻辑(比喻版):

把宿舍分成A、B两个区域,平时只用A区放东西:

  • 第一步:检查A区,把还在用的物品搬到B区;
  • 第二步:把A区剩下的垃圾全部清空;
  • 第三步:下次用B区,重复上述步骤(A、B区互换)。

优点:

  • 效率高:不用逐个标记垃圾,只搬有用的东西;
  • 无内存碎片:清空后的区域是连续的,能放大对象。

缺点:

浪费内存:永远有一半区域是空的,相当于“花双倍房租只用到一半空间”。

应用场景:

JVM的“年轻代”(新创建的对象都在这)默认用这个算法——因为年轻代的对象大多是“短命鬼”(很快变成垃圾),需要频繁清理,复制算法刚好高效。

3. 标记-整理算法(解决碎片问题的“进阶版”)

核心逻辑(比喻版):

  • 第一步(标记):和“标记-清除”一样,贴标签标记垃圾;
  • 第二步(整理):把所有还在用的物品挪到宿舍的一侧,挤成连续的空间;
  • 第三步(清除):把另一侧的垃圾全部清空。

优点:

  • 无内存碎片:有用的东西都挤在一起,空间利用率高;
  • 比复制算法节省内存(不用分两个区)。

缺点:

整理阶段需要移动对象,会暂停程序运行(专业叫“STW”,Stop The World),卡顿时间稍长。

应用场景:

JVM的“老年代”(存活时间长的对象)常用这个算法——老年代的对象少但体积大,不怕卡顿一点,更怕内存碎片。

4. 分代收集算法(“按年龄分区打扫”,实际最常用)

核心逻辑(比喻版):

把宿舍分成“青年区”(年轻代)和“老年区”(老年代):

  • 青年区:住刚搬进来的年轻人(新创建的对象),这些人流动性大,用“复制算法”快速打扫;
  • 老年区:住住了很久的老人(存活超过一定时间的对象),这些人稳定,用“标记-整理算法”慢慢打扫。

为什么要分代?

就像学校打扫卫生:

  • 教室(年轻代)人多、垃圾多,要频繁快速扫(复制算法);
  • 教师办公室(老年代)人少、东西多,不用频繁扫,扫的时候要仔细(标记-整理)。

应用场景:

所有商用JVM(比如HotSpot)的默认算法,是前面3种算法的组合使用。

四、小白总结:核心知识点速记

  1. JVM参数核心记3类:内存分配(-Xms/-Xmx)、垃圾回收器(-XX:+UseG1GC)、调试(-XX:+PrintGCDetails);
  2. 垃圾回收算法不用记原理细节,记住:
    • 年轻代用复制算法(快);
    • 老年代用标记-整理算法(省空间);
    • 实际用的是分代收集(组合拳);
  3. 新手调优建议:
    • 先把-Xms和-Xmx设为相同值(比如2g);
    • JDK8及以上直接用默认的G1GC;
    • 遇到OOM问题,开启HeapDump参数,分析内存快照。

五、最后说句掏心窝的话

JVM调优不是“一蹴而就”的事,小白不用一开始就追求“调得最优”,先理解核心概念,再结合实际项目慢慢尝试——比如给你的第一个Spring Boot项目设置-Xms1g -Xmx1g -XX:+UseG1GC,看看程序运行有什么变化,比死记硬背参数有用得多。

如果觉得本文有用,欢迎收藏起来慢慢看,也可以转发给刚学Java的小伙伴~

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
26
获赞与收藏
80

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消