零、本文纲要
- 一、 栈
案例一:线程CPU占用过多定位方法
案例二:程序运行很长时间没有结果 - 二、 堆
堆内存诊断工具
案例:垃圾回收后,内存占用仍然很高 - 三、 方法区
案例:StringTable调优 - 四、 垃圾回收
- 堆分析工具
- JVM相关参数
- 垃圾回收器设置
一、 栈
案例一:线程CPU占用过多定位方法
1. 查看进程状态(实时信息)
命令:top
2. 查看进程线程cpu信息
命令:ps H -eo pid,tid,%cpu
ps:查看进程情况
H:打印进程信息
-eo:规定感兴趣的信息
pid:进程id
tid:线程id
%cpu:CPU使用率
3. 查看指定进程信息
命令:ps H -eo pid,tid,%cpu | grep [pid]
[pid]:填写指定进程id
4. jstack查看具体进程中所有线程信息
命令:jstack [pid]
5. 进制换算确定具体线程
tid[十进制] → nid=0x****[十六进制]
6. 在线程信息中确定第几行代码
([****].java:[**row])
案例二:程序运行很长时间没有结果
1. 让程序在后台运行
nohup Command [args] [&]
命令:nohup java .. &
nohup:no hang up(不挂起),用于在系统后台不挂断地运行命令
&:让命令在后台执行,终端退出后命令仍旧执行
2. jstack查看具体进程中所有线程信息
命令:jstack [pid]
查看输出信息,确定问题位置(死锁deadlock)。
二、 堆
堆内存诊断工具
1. jps工具
命令:jps
查看当前系统中有哪些java进程
2. jmap工具
命令:jmap -heap [pid]
JDK8命令:jhsdb jmap --heap --pid [pid]
查看堆内存占用情况(某一时刻)
3. jconsole工具
图形界面的、多功能的检测工具,可以连续检测
案例:垃圾回收后,内存占用仍然很高
1. jps查看进程id
命令:jps
2. jmap查看堆内存使用情况
命令:jmap -heap [pid]
3. jconsole动态监测
命令:jconsole
点击 → 执行GC(G)
4. jvisualvm查看可视化虚拟机界面
点击 → 堆Dump
截取某一具体时刻的堆内存信息(包含对象信息)
点击 → 查找[20]保留大小最大的对象:查找
三、 方法区
1. 反编译查看类的相信信息
命令:javap -v **.class
案例:StringTable调优
1. 设置字符串常量池表桶数量
命令:-XX:StringTableSize=200000
减少hash碰撞,提升效率
2. 将字符串对象放入常量池,减少重复对象占用内存
s.intern();
四、 垃圾回收
1. 堆分析工具
Memory Analyzer(MAT)
MAT官方下载地址
- ① MAT使用:查看GC Root对象
Ⅰ 查看当前运行的进程
命令:jps
Ⅱ 把当前进程信息输出到二进制文件
命令:jmap -dump:format=b,live,file=[fileName].bin [pid]
-dump:输出
format:指定格式
b:二进制
live:进行一次垃圾回收(Full GC)
file:输出到文件
Ⅲ 使用MAT打开.bin文件
2. JVM相关参数
含义 | 参数 |
---|---|
堆初始大小 | -Xms |
堆最大大小 | -Xmx 或 -XX:MaxHeapSize=size |
新生代大小 | -Xmn 或 -XX:NewSize=size -XX:MaxNewSize=size |
幸存区比例(动态) | -XX:InitialSurvivorRatio=ratio -XX:+UseAdaptiveSizePolicy |
幸存区比例 | -XX:SurvivorRatio=ratio |
晋升阈值 | -XX:MaxTenuringThreshold=threshold |
晋升详情 | -XX:+PrintTenuringDistribution |
GC详情 | -XX:+PrintGCDetails -verbose:gc |
FullGC 前 MinorGC | -XX:+ScavengeBeforeFullGC |
说明:
-XX:SurvivorRatio=8
,表示伊甸园比例为8,From、To各占1。
3. 垃圾回收器设置
- ① 串行
-XX:+UseSerialGC
表示使用:Serial + SerialOld
Serial:新生代,使用复制算法
SerialOld:老年代,使用标记整理算法
- ② 吞吐量优先
-XX:+UseParallelGC -XX:+UseParallelOldGC
-XX:+UseAdaptiveSizePolicy
-XX:GCTimeRatio=ratio
-XX:MaxGCPauseMillis=ms
-XX:ParallelGCThreads=n
说明:
JDK1.8默认开启-XX:+UseParallelGC
-XX:GCTimeRatio=ratio
,其中ratio默认为99。表示1/(1+99),垃圾回收时间不能超过0.01。一般也可以设置为19,表示1/(1+19),不超过0.05。
-XX:MaxGCPauseMillis=ms
,表示最大暂停毫秒数,默认是200ms。该目标与ratio需协调使用。
表示使用:Parallel + ParallelOld
Parallel:新生代,使用复制算法
ParallelOld:老年代,使用标记整理算法
- ③ 响应时间优先
-XX:+UseConcMarkSweepGC -XX:UseParNewGC
-XX:ParallelGCThreads=n -XX:ConcGCThreads=threads
-XX:CMSInitiatingOccupancyFraction=percent
-XX:+CMSScavengeBeforeRemark
说明:
-XX:ParallelGCThreads=n
设置并行线程数,-XX:ConcGCThreads=threads设置并发标记清理线程数,一般设置为前者1/4。比如并行线程数4,则设置1个线程标记清理。
-XX:CMSInitiatingOccupancyFraction=percent
设置执行垃圾回收的内存占比,默认值69%。多余的空间一般用于浮动垃圾存储。
-XX:+CMSScavengeBeforeRemark
设置重新标记之前对新生代进行一次垃圾回收,减轻后续重新标记的压力。
表示使用:ParNew + ConcMarkSweep(SerialOld)
ParNew:新生代,使用复制算法
ConcMarkSweep:老年代,使用标记清除(并发的)。标记清除内存碎片过多,则会导致并发清除失败,则使用SerialOld垃圾回收器。
- ④ G1(Garbage First)
-XX:+UseG1GC
-XX:G1HeapRegionSize=size
-XX:MaxGCPauseMillis=time
-XX:InitiatingHeapOccupancyPercent=percent
说明:
-XX:MaxGCPauseMillis=time
默认暂停时间为200ms
-XX:InitiatingHeapOccupancyPercent=percent
默认是45%
表示使用:G1(JDK9是默认使用)
整体使用标记+整理算法,两个区域之间使用复制算法。
G1垃圾回收阶段:
- Ⅰ Young Collection
E逐渐占满,则会触发Young GC,会STW
把E中的幸存对象拷贝到S中
S中的对象年龄到达阈值,则会晋升到O中
- Ⅱ Young Collection + Concurrent Mark
Young GC时会进行GC Root的初始标记
老年代占用对空间达到比例阈值时(默认为45%),会进行并发标记,不会STW
-XX:InitiatingHeapOccupancyPercent=percent
- Ⅲ Mixed Collection
会对E、S、O进行全面垃圾回收
最终标记(Remark)会STW
拷贝存活(Evacuation)会STW
-XX:MaxGCPauseMillis=time
,G1会优先选择O回收价值比较高的进行回收,以达到此时间目标
- ⑤ Full GC
Ⅰ SerialGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
Ⅱ ParallelGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc
Ⅲ CMS
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足 - 并发清除/并发失败,串行清除
Ⅳ G1
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足 - 并发标记、混合清除/如果垃圾产生速度高于清除速度,则会串行清除
五、结尾
以上即为JVM基础栈、堆、方法区、垃圾回收的全部内容,感谢阅读。