天天看点

jvm性能优化1 JVM内存模型2 调优诊断工具3 垃圾回收过程4 调优目的:减少full gc的频率-STW(Stop The World)

文章目录

  • 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内存模型

jvm性能优化1 JVM内存模型2 调优诊断工具3 垃圾回收过程4 调优目的:减少full gc的频率-STW(Stop The World)

2 调优诊断工具

2.1 jvisualvm

2.2 阿里arthas

2.2.1 直接下载jar包运行

java -jar arthas-boot.jar
           

2.2.2 常用命令

1、dashboard 显示所有线程的执行情况

jvm性能优化1 JVM内存模型2 调优诊断工具3 垃圾回收过程4 调优目的:减少full gc的频率-STW(Stop The World)

可以看到上述程序执行的堆内存情况(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以上的对象进入老年代。动态年龄判断应该是这样子的。说的通俗一点:就是年龄从小到大对象的占据空间的累加和,而不是某一个特定年龄对象占据的空间。

案例:亿级网站抢购活动分析

jvm性能优化1 JVM内存模型2 调优诊断工具3 垃圾回收过程4 调优目的:减少full gc的频率-STW(Stop The World)

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已经被标记为垃圾的对象,用户线程后续继续使用了(错标记)。