JVM调优
什么是JVM调优,调优的指标是什么?
JVM调优指的就是对当前系统进行性能调优,简单来说就是尽可能使用较小的内存和CPU来让JAVA程序获得更高的吞吐量及较低的延迟。
调优常见的指标:
- 吞吐量:是指不考虑垃圾收集引起的停顿时间或内存消耗,应用达到的最高性能指标。
- 延迟:缩短由于垃圾收集引起的停顿时间或者完全消除因垃圾收集所引起的停顿,避免应用运行时发生抖动。
- 内存占用:垃圾收集器流畅运行所需要的内存数量。
何时需要去做JVM调优(为什么做)
总结下来:吞吐量低、延迟高、经常出现OOM等
- Ful GC次数频繁,分配的内存不够
- GC停顿时间过长
- 应用出现OOM等内存异常
- 系统吞吐量与响应性能不高或持续下降
一般的工程项目是不需要去调优的。从代码处考量优化
JVM调优的基本原则
JVM调优是一个手段,但不是一定所有问题都可以通过JVM进行调优解决
- 大多数的Java应用不需要进行JVM优化
- 大多数导致GC问题的原因是代码层面的问题导致的
- 减少使用全局变量和大对象,减少创建对象的数量
- 分析GC情况优化代码比JVM参数更好
- 有限架构调优和代码调优,JVM优化优先级放到最低
JVM调优的目标
堆内存的基本结构
在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常分为下面三部分
- 新生代内存(Young Generation)
- 老生代(Old Generation)
- 永久代(Permanent Generation)
下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代
(图片来自Java Guide)
JDK 8 版本之后 PermGen(永久) 已被 Metaspace(元空间) 取代,元空间使用的是直接内存 。
GC算法及常用的垃圾收集器
- 对象存活分析?
引用计数法
- 给JAVA对象添加一个引用计数器
- 每当有一个地方引用它时,计数器+1,引用失效,则-1
- 当计数器不为0时,判断该对象存活;否则判断对象死亡
优点:实现简单,判断高效。
缺陷:无法解决对象间相互循环引用的问题,由于该算法存在判断漏洞,所以JAVA虚拟机没有采用该算法判断JAVA对象是否存活。
objA.name= objB;
objB.name= objA;
可达性分析算法
- 将一系列的GC Roots对象作为起点,从这些起点开始向下搜索
- 当一个对象到GC Root没有任何引用链相连时,则判断该对象不可达。
常见的可以作为GC Root对象的有
- 虚拟机栈中引用的对象
- 本地方法栈中JNI引用对象
- 方法区中常量、类静态属性引用的对象
常见的GC算法
标记-清除
标记-复制算法
缺点: 1. survive区域浪费,可能存在大量复制动作
标记-整理
缺点: 效率不高
常见的垃圾回收器
年轻代垃圾收集器
- Serial收集器
- ParNew收集器
老年代垃圾收集器
- Serial Old收集器
- Parallel Old收集器
- CMS收集器
不存在物理隔离分代
- G1(横跨年轻代和老年代)
更多见:Java Guide JVM篇