网站首页 > 文章精选 正文
一、JVM内存结构回顾
在开始调优前,我们先简单回顾下JVM内存结构:
JVM内存区域
├── 堆(Heap) - 对象生存的主要场所
│ ├── 新生代(Young Generation) - 新创建的对象
│ │ ├── Eden区 - 对象出生地
│ │ ├── Survivor区 (S0和S1) - 幸存者暂住地
│ └── 老年代(Old Generation) - 长期存活对象
├── 方法区(Method Area) - 类信息、常量池等
├── 虚拟机栈(VM Stack) - 线程私有,方法调用
└── 本地方法栈(Native Stack) - native方法调用
二、JVM核心参数详解
1. 堆内存设置
-Xms和-Xmx
java -Xms512m -Xmx2g -jar myapp.jar
- -Xms:初始堆大小(如512m)
- -Xmx:最大堆大小(如2g)
最佳实践:
- 生产环境建议设置-Xms和-Xmx相同,避免堆扩容带来的性能损耗
- 通常设置为可用物理内存的70-80%(需为系统和其他进程预留空间)
2. 新生代与老年代比例
-XX:NewRatio
-XX:NewRatio=2
- 表示新生代:老年代 = 1:2
- 默认值2(即老年代占2/3,新生代1/3)
-XX:SurvivorRatio
-XX:SurvivorRatio=8
- Eden区与Survivor区的比例
- 默认值8(即Eden:S0:S1 = 8:1:1)
调整示例:
对于创建大量临时对象的应用(如数据处理),可以增大新生代:
-XX:NewRatio=1 -XX:SurvivorRatio=4
3. 元空间(Metaspace)设置
Java 8+用Metaspace替代了永久代(PermGen)
-XX:MetaspaceSize 和 -XX:MaxMetaspaceSize
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
- 默认不限制大小(受限于系统内存)
- 建议设置上限避免内存泄漏导致问题
三、垃圾回收器选择
JVM提供了多种GC算法,常见组合:
- 串行回收器(单线程)
-XX:+UseSerialGC
- 单线程工作,简单高效
- 适合内存<100MB的单核CPU应用
2. 并行回收器(吞吐量优先)
-XX:+UseParallelGC -XX:ParallelGCThreads=4
- 多线程并行GC
- -XX:ParallelGCThreads设置GC线程数(通常等于CPU核心数)
3. CMS回收器(低延迟)
-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75
- 减少停顿时间,适合Web应用
- -XX:CMSInitiatingOccupancyFraction=75:老年代75%时触发GC
4. G1回收器(平衡型,JDK9+默认)
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
- -XX:MaxGCPauseMillis设置目标最大停顿时间
- 适合堆内存>6GB的应用
四、其它参数配置
1. GC日志
-XX:+PrintGCDetails # 打印GC详细信息
-XX:+PrintGCDateStamps # 添加时间戳
-Xloggc:/logs/gc.log # 指定日志路径
-XX:+UseGCLogFileRotation # 启用日志轮转
-XX:NumberOfGCLogFiles=5 # 保留5个日志文件
-XX:GCLogFileSize=20M # 每个日志文件不超过20MB
- 作用:通过日志分析GC频率、停顿时间,定位性能瓶颈。
- 工具:可使用GCViewer或Eclipse MAT可视化日志。
2. 字符串去重:减少内存占用
-XX:+UseStringDeduplication # 开启字符串去重(JDK8+)
合并重复的字符串对象,节省堆内存(适合字符串操作频繁的场景)。
3. 禁用显示GC调用
-XX:+DisableExplicitGC # 禁用System.gc()调用
System.gc()可能引发不必要的Full GC,打乱JVM的回收节奏。
4. 线程栈大小:避免栈溢出
-Xss1m # 设置线程栈为1MB(默认可能更大)
高并发场景下,若线程数过多,需减小栈大小以节省内存。
五、实战案例
场景描述:
- 硬件
- :8核CPU,32GB内存。
- 需求
- :高并发电商系统,需低延迟、高吞吐。
调优参数:
java \
-Xms16g -Xmx16g \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g \
-Xloggc:/logs/gc.log -XX:+PrintGCDetails \
-XX:+UseStringDeduplication -XX:+DisableExplicitGC \
-jar my-ecommerce-app.jar
-Xms16g -Xmx16g # 占用一半内存,剩余给操作系统和非堆
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 #选择G1GC
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g #元空间配置
-Xloggc:/logs/gc.log -XX:+PrintGCDetails #GC日志与监控
-XX:+UseStringDeduplication -XX:+DisableExplicitGC #其他优化
六、实用工具推荐
- 命令行工具:
- jps:查看Java进程
- jstat:监控GC和内存
- jmap:堆内存分析
- jstack:线程栈分析
- 图形化工具:
- VisualVM
- JConsole
- Eclipse MAT(内存分析)
- 生产级APM:
- Arthas(阿里开源的Java诊断工具)
- Prometheus + Grafana(监控)
- SkyWalking(分布式追踪)
猜你喜欢
- 2025-07-23 JVM中哪些是线程共享区,哪些是线程独占区
- 2025-07-23 线上服务 FGC 问题排查,看这篇就够了
- 2025-07-23 JVM运行时内存区域、堆内存分段机制
- 2025-07-23 JVM运行数据区深度解析(jvm运行时区域)
- 2025-07-23 开发者必备!线上内存泄漏排查的 8 个 Linux 实战工具
- 2025-07-23 内存溢出满分排查步骤,看完不用担心拿不到Offer了
- 2025-07-23 关于JVM调优,看这篇就够了(jvm调优实战简书)
- 2025-07-23 那么大个对象的垃圾回收有什么不同
- 2025-07-23 GC分代年龄为什么是15?(对象gc的分代年龄保存在)
- 2025-07-23 求你了,别再说 Java 对象都是在堆内存上分配空间了
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)
- fmt.println (52)