文章目录
- 1 JVM内存模型
- 2 调优诊断工具
-
- 2.1 jvisualvm
- 2.2 阿里arthas
-
- 2.2.1 直接下载jar包运行
- 2.2.2 常用命令
- 3 垃圾回收过程
-
- 3.1 垃圾回收机制
- 3.2 回收过程
-
- 3.2.1 minor gc:当Eden区放满,回收新生代空间
- 3.2.2 新生代转移到老年代
-
- 3.2.2.1 长期存活的对象
- 3.2.2.2 Survivor区域存满,会把这些对象拷贝老年代
- 3.2.2.3 大对象进入老年代
- 3.2.2.4 对象动态年龄判断
- 3.2.3 full gc:回收整个堆空间
- 4 调优目的:减少full gc的频率-STW(Stop The World)
-
- 4.1 为什么要设计STW?
1 JVM内存模型
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYTMfhHLlN3XnxCM38FdsYkRGZkRG9lcvx2bjxCMy8VZ6l2cs0TTU9UNFpmYxgGWhFDatVWQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5YmY1I2NmFzYmJGOhFmM4UGZ1QDOllTNiNWOmVTNhF2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2 调优诊断工具
2.1 jvisualvm
2.2 阿里arthas
2.2.1 直接下载jar包运行
java -jar arthas-boot.jar
2.2.2 常用命令
1、dashboard 显示所有线程的执行情况
可以看到上述程序执行的堆内存情况(Eden区、Survivor区,old区,元空间,gc等)
2、thread [threadId] 显示某个thread的详细情况
3、thread -b 显示阻塞情况
4、反编译:jad com.hd.Test
反编译可以帮助开发人员确定代码是否成功发布
3 垃圾回收过程
3.1 垃圾回收机制
可达性分析。从GC ROOT(栈里的局部变量,方法区的静态变量,常量)找到可达的对象,标记这些对象是非垃圾。
3.2 回收过程
3.2.1 minor gc:当Eden区放满,回收新生代空间
- 通过可达性分析标记Eden区域和S0区域的垃圾
- 执行gc回收
- 将Eden和S0的非垃圾对象复制到S1区,将他们的年龄+1.
- 结束回收。后续回收的空间是Eden和S1。
3.2.2 新生代转移到老年代
3.2.2.1 长期存活的对象
默认15岁,CMS默认6岁。通过参数
XX:MaxTenuringThreshold
设置。
3.2.2.2 Survivor区域存满,会把这些对象拷贝老年代
3.2.2.3 大对象进入老年代
大对象就是需要大量连续存储空间的对象(比如字符串、数组等)。
JVM参数
-XX:PretenureSizeThreshold
可以设置大对象的大小。如果超过这个值则对象直接进入老年代。该参数只在
Serial
和
ParNew
两个收集器下有效。
好处:避免大对象分配内存时的复制操作而降低效率
3.2.2.4 对象动态年龄判断
年龄1+年龄2+年龄3+年龄N的对象加起来的空间,大于survivor区域的一半(具体的比例通过参数
-XX:TargetSurvivorRatio
设置),就会让年龄N和年龄N以上的对象进入老年代。动态年龄判断应该是这样子的。说的通俗一点:就是年龄从小到大对象的占据空间的累加和,而不是某一个特定年龄对象占据的空间。
案例:亿级网站抢购活动分析
3.2.3 full gc:回收整个堆空间
1、当老年代存满时,会触发full gc
2、调用System.gc()方法
4 调优目的:减少full gc的频率-STW(Stop The World)
minor gc和full gc都会导致STW,导致应用程序暂停。
如果gc时间比较长,则STW时间也会很长,就会造成程序响应很慢。
4.1 为什么要设计STW?
如果不STW有什么坏处?【对象状态在用户线程执行过程中不断变化,造成错标记或漏标记】
- gc过程中,用户线程还在进行,可能会出现gc到一半的时候,已经判断为非垃圾的对象变成了垃圾(漏标记)。
- gc已经被标记为垃圾的对象,用户线程后续继续使用了(错标记)。