一、JVM基础概念
一、JVM的设计目标
-
一次编译,到处运行(跨平台)
➔ Java编译成字节码,由JVM在不同平台解释/编译执行,实现跨平台。 -
内存管理与垃圾回收
➔ JVM统一负责内存分配和回收,降低内存泄漏的风险。 -
性能优化
➔ JIT(即时编译器)、逃逸分析、栈上分配、方法内联等,动态提高程序运行速度。 -
安全性和隔离性
➔ 类加载机制、沙箱安全模型,限制程序访问非法资源。 -
多语言支持(了解)
➔ 除了Java,还能运行Kotlin、Scala、Groovy等基于JVM的语言。
二、JVM主要学习哪些东西
1. JVM整体架构
- 类加载子系统(Class Loader) ☆☆☆☆☆
- 运行时数据区(堆、栈、方法区、PC寄存器、本地方法栈) ☆☆☆☆☆
- 执行引擎(解释器 + JIT编译器)
- 本地接口(JNI)
2. 类加载机制
- 双亲委派模型 ☆☆☆☆☆
- 类的生命周期(加载、验证、准备、解析、初始化、使用、卸载) ☆☆☆☆☆
3. 内存模型与GC
- Java内存模型(JMM) ☆☆☆☆☆
- 堆、非堆、直接内存
- 垃圾回收器分类(Serial、Parallel、CMS、G1、ZGC、Shenandoah) ☆☆☆☆☆
- GC日志分析 ☆☆☆☆☆
- 新生代、老年代、永久代/元空间(PermGen/MetaSpace)
4. 字节码执行原理 了解
- JVM指令集
- 栈帧结构
- 本地方法接口调用(JNI)
5. 性能优化
- JIT编译优化(热点探测、方法内联)
- 逃逸分析、锁消除、锁粗化、偏向锁、轻量级锁 ☆☆☆☆☆
- 内存调优参数 ☆☆☆☆☆
- GC调优策略 ☆☆☆☆☆
6. 常见工具
- jps、jstack、jmap、jhat、jconsole、visualvm、arthas ☆☆☆☆☆
三、JVM调优最佳实践 ☆☆☆☆☆
基本上遵循下面的步骤
1. 确定目标
- 响应时间优先?吞吐量优先?内存占用优先?
➔ 目标不同,调优策略不同。
2. 合理设置堆内存
- -Xms(初始堆大小) = -Xmx(最大堆大小),避免堆自动扩容
- 年轻代(新生代)和老年代比例合理配置(-XX:NewRatio)
3. 选择合适的GC算法
- 小应用、低延迟 ➔ G1 GC、ZGC
- 批处理、大吞吐量 ➔ Parallel GC
- 对响应敏感 ➔ CMS GC(慎用,已被G1替代)
4. 监控和分析
- 监控指标: GC次数、GC时间、FullGC频率、堆使用率、线程数量、响应延迟
- 工具使用: Arthas、VisualVM、jstat、jstack、jmap
- GC日志启用:
-Xlog:gc*:file=gc.log:time,uptime,level,tags
5. 避免常见问题
避免不合理的对象创建,减少短命对象
大对象直接进入老年代,合理设置 PretenureSizeThreshold
及时关闭连接、释放资源,防止内存泄漏
线程池合理使用,避免频繁创建销毁线程
6. 代码层面优化
尽量使用局部变量,减少对象逃逸到堆
初始化集合时设定合理容量,避免频繁扩容
对大对象缓存可使用软引用(SoftReference)、弱引用(WeakReference)
7. 启动参数推荐模板 (下面只是顺便写个例子 后续博客会详细说明)
-server
-Xms4g
-Xmx4g
-Xmn1g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+UseStringDeduplication
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump