一、环境
1.启动容器
为了方便测试,使用 docker 启动一个 ubuntu 系统。设置内存为 4G。
docker run -itd --name ubuntu_1 -m 4G --cap-add CAP_SYS_PTRACE ubuntu:20.04
注意这里设置 CAP_SYS_PTRACE,表示 允许跟踪任何进程,否则使用 jmap 查看堆信息,可能会出现 Operation not permitted 异常
2.安装 jdk
apt install openjdk-8-jdk
apt install openjdk-8-dbg
注意需要安装 openjdk-8-dbg,否则使用 jmap 可能会出现 unknown CollectedHeap type 异常
root@761eaf876cf2:/# java -version
openjdk version "1.8.0_432"
看出安装的 openjdk 版本为 1.8.0_432
二、UseParallelGC
jdk 1.8.0_432 默认的垃圾回收器为 UseParallelGC
1.启动应用
root@761eaf876cf2:/# java -jar app.jar
root@761eaf876cf2:/# jps -l
149 app.jar
root@761eaf876cf2:/# jinfo -flags 149
Attaching to process ID 149, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.432-bga
Non-default VM flags: -XX:CICompilerCount=12 -XX:InitialHeapSize=67108864 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=357564416 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=22020096 -XX:OldSize=45088768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
Command line:
通过 jinfo 可以查看,默认参数值为:
-XX:InitialHeapSize=67108864 (64MB) (1024*4MB * 1/64,物理内存的 1/64)
-XX:MaxHeapSize=1073741824 (1024MB) (1024*4MB * 1/4,物理内存的 1/4)
-XX:MaxNewSize=357564416 (341MB)
-XX:NewSize=22020096 (21MB)
-XX:OldSize=45088768 (43MB)
-XX:MinHeapDeltaBytes=524288 (0.5MB)
2.程序刚启动时
jmap 查看堆使用情况
MaxHeapSize (最大堆空间大小) 默认占物理内存的 1/4
root@761eaf876cf2:/# jmap -heap 149
Heap Configuration:
MinHeapFreeRatio = 0 # 最小堆使用比例,堆内存剩余空间低于这个比例时会开始变大
MaxHeapFreeRatio = 100 # 最大堆可用比例,当堆内存剩余空间高于这个比例时,会开始变小
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 22020096 (21.0MB) # 新生代分配大小
MaxNewSize = 357564416 (341.0MB) # 最大可新生代分配大小
OldSize = 45088768 (43.0MB) # 老年代大小
NewRatio = 2 # 新生代(2个Survivor区和Eden区 )与老年代的堆空间比值,表示新生代:老年代=1:2
SurvivorRatio = 8 # 两个Survivor区和Eden区的堆空间比值为 8,表示 S0 : S1 :Eden = 1:1:8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 103809024 (99.0MB)
used = 54169080 (51.65966033935547MB)
free = 49639944 (47.34033966064453MB)
52.18147509025805% used
From Space:
capacity = 6815744 (6.5MB)
used = 6798512 (6.4835662841796875MB)
free = 17232 (0.0164337158203125MB)
99.74717360276442% used
To Space:
capacity = 7864320 (7.5MB)
used = 0 (0.0MB)
free = 7864320 (7.5MB)
0.0% used
PS Old Generation
capacity = 33554432 (32.0MB)
used = 7070720 (6.7431640625MB)
free = 26483712 (25.2568359375MB)
21.0723876953125% used
12809 interned Strings occupying 1147360 bytes.
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
761eaf876cf2 ubuntu_1 0.15% 290.7MiB / 4GiB 7.10% 7.26kB / 0B 54MB / 467kB 51
3.执行消耗内存操作时
root@761eaf876cf2:/# jmap -heap 149
Heap Configuration:
MinHeapFreeRatio = 0 # 最小堆使用比例,堆内存剩余空间低于这个比例时会开始变大
MaxHeapFreeRatio = 100 # 最大堆可用比例,当堆内存剩余空间高于这个比例时,会开始变小
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 22020096 (21.0MB) # 新生代分配大小
MaxNewSize = 357564416 (341.0MB) # 最大可新生代分配大小
OldSize = 45088768 (43.0MB) # 老年代大小
NewRatio = 2 # 新生代(2个Survivor区和Eden区 )与老年代的堆空间比值,表示新生代:老年代=1:2
SurvivorRatio = 8 # 两个Survivor区和Eden区的堆空间比值为 8,表示 S0 : S1 :Eden = 1:1:8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 119537664 (114.0MB)
used = 87545536 (83.48992919921875MB)
free = 31992128 (30.51007080078125MB)
73.23677999931469% used
From Space:
capacity = 108003328 (103.0MB)
used = 45889968 (43.76408386230469MB)
free = 62113360 (59.23591613769531MB)
42.4894018080628% used
To Space:
capacity = 119013376 (113.5MB)
used = 0 (0.0MB)
free = 119013376 (113.5MB)
0.0% used
PS Old Generation
capacity = 705691648 (673.0MB)
used = 520600464 (496.48329162597656MB)
free = 185091184 (176.51670837402344MB)
73.77166294591034% used
17911 interned Strings occupying 1615960 bytes.
4.java 释放内存后
root@761eaf876cf2:/# jmap -heap 149
Heap Configuration:
MinHeapFreeRatio = 0 # 最小堆使用比例,堆内存剩余空间低于这个比例时会开始变大
MaxHeapFreeRatio = 100 # 最大堆可用比例,当堆内存剩余空间高于这个比例时,会开始变小
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 22020096 (21.0MB) # 新生代分配大小
MaxNewSize = 357564416 (341.0MB) # 最大可新生代分配大小
OldSize = 45088768 (43.0MB) # 老年代大小
NewRatio = 2 # 新生代(2个Survivor区和Eden区 )与老年代的堆空间比值,表示新生代:老年代=1:2
SurvivorRatio = 8 # 两个Survivor区和Eden区的堆空间比值为 8,表示 S0 : S1 :Eden = 1:1:8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 119537664 (114.0MB)
used = 905568 (0.863616943359375MB)
free = 118632096 (113.13638305664062MB)
0.7575587222450658% used
From Space:
capacity = 119013376 (113.5MB)
used = 0 (0.0MB)
free = 119013376 (113.5MB)
0.0% used
To Space:
capacity = 119013376 (113.5MB)
used = 0 (0.0MB)
free = 119013376 (113.5MB)
0.0% used
PS Old Generation
capacity = 705691648 (673.0MB)
used = 22917224 (21.855567932128906MB)
free = 682774424 (651.1444320678711MB)
3.247484090955261% used
17914 interned Strings occupying 1616200 bytes.
可以看出 jvm 并没有把内存归还给操作系统
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
761eaf876cf2 ubuntu_1 0.24% 1.163GiB / 4GiB 29.08% 15.9kB / 4.01kB 0B / 1.89MB 51
三、UseG1GC
1.启动应用
root@5f0a685e03b9:/# java -XX:+UseG1GC -jar app.jar
root@5f0a685e03b9:/# jps -l
51 app.jar
root@5f0a685e03b9:/# jinfo -flags 51
Attaching to process ID 51, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.432-bga
Non-default VM flags: -XX:CICompilerCount=12 -XX:ConcGCThreads=3 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=67108864 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=643825664 -XX:MinHeapDeltaBytes=1048576 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
Command line: -XX:+UseG1GC
通过 jinfo 可以查看,参数值为:
-XX:InitialHeapSize=67108864 (64MB) (1024*4MB * 1/64,物理内存的 1/64)
-XX:MaxHeapSize=1073741824 (1024MB) (1024*4MB * 1/4,物理内存的 1/4)
-XX:MaxNewSize=643825664 (614MB)
-XX:G1HeapRegionSize=1048576 (1MB)
-XX:MarkStackSize=4194304 (4MB)
-XX:MinHeapDeltaBytes=1048576 (1MB)
2.程序刚启动时
jmap 查看堆使用情况
MaxHeapSize (最大堆空间大小) 默认占物理内存的 1/4
root@5f0a685e03b9:/# jmap -heap 51
Attaching to process ID 51, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.432-bga
using thread-local object allocation.
Garbage-First (G1) GC with 13 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 1363144 (1.2999954223632812MB) # 新生代分配大小
MaxNewSize = 643825664 (614.0MB) # 最大可新生代分配大小
OldSize = 5452592 (5.1999969482421875MB) # 老年代大小
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions = 1024
capacity = 1073741824 (1024.0MB)
used = 37017088 (35.30224609375MB)
free = 1036724736 (988.69775390625MB)
3.4474849700927734% used
G1 Young Generation:
Eden Space:
regions = 14
capacity = 33554432 (32.0MB)
used = 14680064 (14.0MB)
free = 18874368 (18.0MB)
43.75% used
Survivor Space:
regions = 5
capacity = 5242880 (5.0MB)
used = 5242880 (5.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 17
capacity = 28311552 (27.0MB)
used = 17094144 (16.30224609375MB)
free = 11217408 (10.69775390625MB)
60.378689236111114% used
12821 interned Strings occupying 1147736 bytes.
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5f0a685e03b9 ubuntu_1 0.14% 234.6MiB / 4GiB 5.73% 3.42kB / 0B 176kB / 324kB 70
3.执行消耗内存操作时
root@5f0a685e03b9:/# jmap -heap 51
Attaching to process ID 51, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.432-bga
using thread-local object allocation.
Garbage-First (G1) GC with 13 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 1363144 (1.2999954223632812MB) # 新生代分配大小
MaxNewSize = 643825664 (614.0MB) # 最大可新生代分配大小
OldSize = 5452592 (5.1999969482421875MB) # 老年代大小
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions = 1024
capacity = 1073741824 (1024.0MB)
used = 1072915576 (1023.212028503418MB)
free = 826248 (0.7879714965820312MB)
99.92304965853691% used
G1 Young Generation:
Eden Space:
regions = 0
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
0.0% used
Survivor Space:
regions = 0
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
0.0% used
G1 Old Generation:
regions = 0
capacity = 1073741824 (1024.0MB)
used = 1072915576 (1023.212028503418MB)
free = 826248 (0.7879714965820312MB)
99.92304965853691% used
10904 interned Strings occupying 1000736 bytes.
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5f0a685e03b9 ubuntu_2 157.00% 1.233GiB / 4GiB 30.83% 5.09kB / 1.05kB 176kB / 1.22MB 69
4.java 释放内存后
root@5f0a685e03b9:/# jmap -heap 51
Attaching to process ID 125, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.432-bga
using thread-local object allocation.
Garbage-First (G1) GC with 13 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB) # 最大堆空间大小
NewSize = 1363144 (1.2999954223632812MB) # 新生代分配大小
MaxNewSize = 643825664 (614.0MB) # 最大可新生代分配大小
OldSize = 5452592 (5.1999969482421875MB) # 老年代大小
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions = 1024
capacity = 1073741824 (1024.0MB)
used = 10084584 (9.617408752441406MB)
free = 1063657240 (1014.3825912475586MB)
0.9392000734806061% used
G1 Young Generation:
Eden Space:
regions = 0
capacity = 10485760 (10.0MB)
used = 0 (0.0MB)
free = 10485760 (10.0MB)
0.0% used
Survivor Space:
regions = 0
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
0.0% used
G1 Old Generation:
regions = 10
capacity = 24117248 (23.0MB)
used = 10084584 (9.617408752441406MB)
free = 14032664 (13.382591247558594MB)
41.814820662788726% used
13226 interned Strings occupying 1180144 bytes.
可以看出 jvm 并把内存归还给操作系统
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5f0a685e03b9 ubuntu_1 0.28% 220.6MiB / 4GiB 5.39% 5.42kB / 1.75kB 49.2kB / 401kB 70