概念

volatile

能禁止指令重排序,所以 volatile 能在一定程度上保证有序性

年轻代

Eden

Survivor

老年代

Tenured:1. 回收多次回收不了的 2. 大对象

GC

垃圾

没有任何引用指向的对象或多个对象「循环引用」

定位垃圾算法

  1. 引用计数「Reference Count」

  2. 根可达算法「Root Searching」

    GC Roots:线程栈变量、静态变量、常量池、JNI 指针、Class 对象

回收算法

  1. Mark-Sweep「标记清除」——位置不连续、产生碎片
  2. 拷贝算法:没有碎片、浪费空间
  3. 标记压缩「Mark Compact」:没有碎片、效率偏低

JVM 分代算法

  1. 部分垃圾回收器使用的模型
  2. 新生代+老年代+永久代「1.7」/元数据区「1.8」Metaspace
    1. 永久代/元数据——Class 对象
    2. 永久代必须设定大小限制,元数据可以设置,也可以不设置,无上限
    3. 字符串常量 1.7-永久代,1.8-堆
    4. MethodArea 逻辑概念-永久代「1.7」、元数据「1.8」
  3. 新生代 = Eden + 2个 Survivor区
    1. YGC:复制算法,大多数对象被回收,活的进入 Survivor「S0」
    2. 再次 YGC,活着的对象 Eden+S0 -> S1
    3. 再次 YGC,Eden+S1->S0
    4. 年龄足够->老年代
    5. S 区装不下->老年代
  4. 老年代
    1. 顽固分子
    2. 老年代满了,FGC,耗时
  5. GC Tuning
    1. 尽量减少 FGC
    2. MinorGC=YGC
    3. MajorGC=FGC

垃圾回收器

image-20200825080111112
  1. Serial——年轻代,串型回收
  2. Parallel Scavenge 年轻代,并行回收
  3. ParNew 年轻代,配合 CMS 并行回收
  4. SerialOld
  5. ParallelOld
  6. CMS「ConcurrentMarkSweep」老年代,并发,垃圾回收和应用同时运行,降低 STW「200ms」
  7. G1「10ms」
  8. ZGC「1ms」 PK C++
  9. Shenandoah
  10. Eplison
  11. JDK 1.8默认垃圾回收器:PS + ParallelOld

调优参数

  1. 参数值(最终生效值)

    1
    --XX:+PrintFlagsFinal
  2. 参数值(默认)

    1
    --XX:+PrintFlagsInitial
  3. 命令行参数

    1
    -XX:+PrintCommandLineFlags

G1

image-20200824235216453
  • 追求响应时间

    • XX:MaxGCPauseMillis 200
    • 对 STW进行控制
  • 灵活

    • 分 Region 回收
    • 优先回收花费时间少、垃圾比例高的 Region
  • 手工指定 Region 大小

    XX:G1HeapRegionSize

  • 工作原理

    • 初始标记——根对象直接引用的对象
    • 并发标记——根追踪算法,不打断应用运行,会监视应用运行
    • 最终标记——
    • 并行回收「复制回收」

优化

1
2
3
4
5
6
7
-XX:+UseG1GC
-XX:MaxGCPauseMillis=500
-XX:ParallelGCThreads=4
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCDateStamps
-Xloggc:./gc.log

参数

堆大小 = 年轻代大小(eden) + 年老代大小(old) + 2 个持久代大小(survivor)

Java JVM 参数设置大全

参数名称 含义 默认值
-Xms 初始堆大小 物理内存的 1/64 (<1GB) 默认 (MinHeapFreeRatio 参数可以调整) 空余堆内存小于 40% 时,JVM 就会增大堆直到 - Xmx 的最大限制.
-Xmx 最大堆大小 物理内存的 1/4 (<1GB)
-Xss 每个线程的堆栈大小 JDK5.0 以后每个线程堆栈大小为 1M, 以前每个线程堆栈大小为 256K. 更具应用的线程所需内存大小进行 调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在 3000~5000 左右
一般小的应用, 如果栈不是很深, 应该是 128k 够用的 大的应用建议使用 256k。这个选项对性能影响比较大,需要严格的测试。(校长)
和 threadstacksize 选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:””
-Xss is translated in a VM flag named ThreadStackSize”
一般设置这个值就可以了。
-Xmn 年轻代大小 (1.4or lator) eden + 2 survivor space PS Eden Space + PS Survivor Space*2
-XX:SurvivorRatio Eden 区与 Survivor 区的大小比值 设置为 8, 则两个 Survivor 区与一个 Eden 区的比值为 2:8, 一个 Survivor 区占整个年轻代的 1/10
-XX:PermSize 设置持久代 (perm gen) 初始值 物理内存的 1/64
-XX:MaxPermSize 设置持久代最大值 物理内存 的 1/4
-XX:NewRatio 年轻代 (包括 Eden 和两个 Survivor 区) 与年老代的比值 (除去持久代) -XX:NewRatio=4 表示年轻代与年老代所占比值为 1:4, 年轻代占整个堆栈的 1/5
Xms=Xmx 并且设置了 Xmn 的情况下,该参数不需要进行设置。

工具路径

JDK 自带 JVM 监测工具路径示例: C:\Program Files\Java\jdk1.8.0_191\bin\

JConsole

jconsole.exe

  • 本地进程

    image-20200617182746364
  • 远程进程

    Tomcat

    • Linux

      catalina.sh

      1
      2
      3
      4
        JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.0.110 -Dcom.sun.management.jmxremote"
      JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9000"
      JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
      JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
    • Windows

      catalina.bat

      1
      2
      3
      4
      set JAVA_OPTS=-Djava.rmi.server.hostname=192.168.0.110 -Dcom.sun.management.jmxremote
      set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=9000
      set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.authenticate=false
      set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.ssl=false

    SpringBoot

    1
    java -server -Xms512m -Xmx768m -jar -Djava.rmi.server.hostname=10.211.55.3 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false files-0.0.1-SNAPSHOT.jar
    image-20200617183556150

jvisualvm

jvisualvm