内存布局

image-20211009101330343

常见的垃圾回收算法

GC 的一些名词

  1. Minor GC
    1. 新生代空间,eden,survivor 区域回收的叫做minor GC
  2. Major GC
    1. 清理Tenured区, 用于回收老年代,出现 Major GC 通常会出现至少一次Minor GC
    2. 清理 Tenured区域,老年代的回收, 出现Major GC 通常至少一次 Minor GC 【可以理解为FUL GC】
  3. FULL GC 【概念上: FULL GC = Major GC + Minor GC + 清理元空间等区域】
    1. 包括整个元空间(metaspace,【永久代】), 新生代,老年代的全局GC

OOM 异常排查

  1. top指令

常见的垃圾收集算法

  1. 复制算法
  2. 标记清除
  3. 标记整理
  4. 分代收集理论

必问的垃圾收集器

  1. G1垃圾收集器

    • 主要步骤: 初始标记,并发标记,重新标记,复制清除
    • 使用算法: 复制+ 标记整理
  2. CMS 垃圾收集器

    • 初始标记 【stop the world】
    • 并发标记
    • 重新标记 【stop the world】
    • 并发清理 【cms concurrent sweep】 阶段
    • 使用算法: 复制+标记清理

CMS 和 G1的对比

  1. G1 在压缩空间有优势
  2. G1将内存空间分成区域(Region) 的方式避免内存碎片问题
  3. Eden ,

常见的参数

-Xint , 表示禁用JIT, 所有字节码都被解释运行, 这个模式速度最慢

-Xmixed, 默认模式,让JIT 根据程序运行的情况,有选择的将某些代码编译成本地代码

GC 调优

目的
  1. GC 的时间够短
  2. GC 的次数够少
  3. 发生 FULL GC 的周期足够的长,时间合理,最好是不发生

内存分配次数

  • Xms: 初始堆的大小 java **-Xmx3550m -Xms3550m -Xmn2g** **-Xss128k**

  • Xmx: 最大堆大小

  • Xss: 每个线程 的 stack大小

  • XX: SurvivorRatio=n, 年轻代中: $eden/s_1$ 区域的比值, 比如 n = 8, eden=8, 那么 s1 = 1, s2和s1 一样也是1

  • XX:MaxPermSize=n: 设置持久代的大小

debug 进程的命令

  • jps, 现在 process show 当前的 java进程
  • jinfo, 运行环境参数
  • jstat , 监视运行状态
  • jstack 观察到 jvM中当前所有线程的运行情况
  • jmap

G1收集器

rememberset

每个 region 都有 个 卡表 card table

image-20211009131408492

对象 直接 可能有各种引用, 可能 eden 区域的引用old 区域的

通过 remember set 快速 找到对应的引用位置

调优分析工具

  1. jps 查看进程状态
  2. jstat 查看进程信息
  3. jstack 查看线程信息,分析线程
  4. jmap 查看堆信息

image-20211009131920791

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[root@VM-0-7-centos ~]# jps
7425 Jps
3203 jar
1429 Bootstrap
[root@VM-0-7-centos ~]# jstat -gc  3203 250 4
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
3712.0 3712.0 3712.0  0.0   30080.0  28864.0   74836.0    62548.4   77480.0 74150.1 9384.0 8772.2    694    3.766  13      1.974    5.741
3712.0 3712.0 3712.0  0.0   30080.0  28864.0   74836.0    62548.4   77480.0 74150.1 9384.0 8772.2    694    3.766  13      1.974    5.741
3712.0 3712.0 3712.0  0.0   30080.0  28864.0   74836.0    62548.4   77480.0 74150.1 9384.0 8772.2    694    3.766  13      1.974    5.741
3712.0 3712.0 3712.0  0.0   30080.0  28864.0   74836.0    62548.4   77480.0 74150.1 9384.0 8772.2    694    3.766  13      1.974    5.741
[root@VM-0-7-centos ~]#

# 只查看 old gc
[root@VM-0-7-centos ~]# jstat -gcnew  3203
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
3712.0 3712.0 3712.0    0.0  1  15 1856.0  30080.0  29366.9    694    3.766
[root@VM-0-7-centos ~]# jstat -gcold  3203
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
 77480.0  74150.1   9384.0   8772.2     74836.0     62548.4    694    13    1.974    5.741
[root@VM-0-7-centos ~]#
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@VM-0-7-centos ~]# jstack 3203
2021-10-09 13:21:54
Full thread dump OpenJDK 64-Bit Server VM (25.302-b08 mixed mode):

"Attach Listener" #23150 daemon prio=9 os_prio=0 tid=0x00007fd0e4006800 nid=0x51c6 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Email_pool_thread_27" #27 prio=5 os_prio=0 tid=0x00007fd0d42b2000 nid=0x7523 waiting on condition [0x00007fd0d88a5000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ee2d93a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"HikariPool-1 housekeeper" #25 daemon prio=5 os_prio=0 tid=0x00007fd0d4235000 nid=0x751f waiting on condition [0x00007fd0d8aa7000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ee12ae70> (a ja
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@VM-0-7-centos ~]# jmap -heap 3203
Attaching to process ID 3203, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.302-b08

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 482344960 (460.0MB)
   NewSize                  = 10485760 (10.0MB)
   MaxNewSize               = 160759808 (153.3125MB)
   OldSize                  = 20971520 (20.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 34603008 (33.0MB)
   used     = 4369832 (4.167396545410156MB)
   free     = 30233176 (28.832603454589844MB)
   12.628474380030777% used
   #      导出文件分析
   
[root@VM-0-7-centos temp]# jmap -dump:file=jvmtool 3203
Dumping heap to /root/temp/jvmtool ...
Heap dump file created