JVM调优

javap查看底层代码执行逻辑

1.反编译class文件:javap -c xxx.class > 目标文件名

Compiled from "Math.java"
public class classdiceng.Math {
  public classdiceng.Math();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class classdiceng/Math
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: aload_1
      12: invokevirtual #5                  // Method computer:()I
      15: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
      18: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      21: ldc           #7                  // String test
      23: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      26: return

  public int computer();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: bipush        10
       9: imul
      10: istore_3
      11: iload_3
      12: ireturn
}

gc 回收

  1. .minor gc只回收年轻代, 采用可达性分析算法 gc roots向下找,直到最后一个,这些标记为非垃圾,其余就为垃圾分代年龄达到15进入老年代(不同垃圾收集器分代年龄可能不同)
  2. full gc 回收整个堆内存 老年代满了之后并不会直接oom,而是先full gc,回收不了,满了。oom

可作为gc roots的有

  • 虚拟机栈(局部变量表中引用的对象)
  • 本地方法栈(本地方法引用的对象)
  • 方法区中静态属性引用的对象
  • 方法区中静态常量池中引用的对象

老年代:2/3

eden:s0:s1=8:1:1

jvm调优工具

jdk自带调优命令 jvisualvm

Alibaba Arthas
dashboad # 监控本地java线程,找出异常线程
thread 线程id # 定位异常线程代码行

测试代码

public class Test1 {
    public static void main(String[] args) {
        while (true){

        }
    }
}

dashboard发现线程id=1占用cpu过高

thread 1

可以看到代码第五行异常:原来室友while true 死循环

常用命令
dashboard # 线程实时监控
thread 线程id # 查看线程具体信息
jad java类 # 反编译java代码

调优实战分析

调优目的

减少gc尤其是full gc,就是减少STW(stop the word)因为gc时,会停掉用户线程,不同垃圾回收器STW实现不一样

为什么要有STW机制

假设没有stw,gc时用户线程不会暂停,在根据gc roots 可达性分析算法查找垃圾时,有些对象不是垃圾, 然后查找其他变量的垃圾对象,没有stw,假设gc线程还没有结束,用户线程已经结束,局部变量就没有了,就没有引用了,就没有垃圾了。但gc之前找到了垃圾,矛盾了,难道要重新找一次?

案例

案例1:是否可以几乎不发送full gc ?

场景:高并发项目,每秒60M,超过了s区的一般,有可能直接进去老年代,这样过个几分钟老年代就满了,j就触发full gc,要调优
其实:每秒60M的数据进入老年代,其实它刚进入老年代不就,它就是是垃圾了,但minor Gc无法回收老年代

优化策略:年轻代内存分配大一些,老年代小一些

案例2

案例1基础上,如果是单机几十万的高并发项目,想kafka,mq,怎么样调优?

首先,内存,cpu肯定要大,这样,堆内存就分的大。像这样,

但是,问题是。eden满时,触发minor gc,但eden是30G,minor gc时间会过长,怎么解决?

解决思想:如果能使eden表边gc边使用,就是每次回收只回收一部分,就使STW短了,用户体验好,而不是回收全部eden,这样新来的对象就可以放在回收后的一部分eden中,就像自定义minor gc触发,G1垃圾收集器就是这样,设置MaxGCPauseMillis定义minor gc回收时间

posted @ 2022-02-22 14:17  jpy  阅读(5)  评论(0编辑  收藏  举报