jstack、堆、GC的常用命令
如果是docker启动的服务,则需要先开启ptrace
而是 Docker 自 1.10 版本开始加入的安全特性。jmap 这类 JDK 工具依赖于 Linux 的 PTRACE_ATTACH,而 Docker 自 1.10 版本开始,默认的 seccomp 配置文件中禁用了 ptrace,如果不开启则会出现一下的错误
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 6: Operation not permitted
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 6: Operation not permitted
jstack
打印某个进程的堆栈信息
jstack [option] <pid>
选项 | 含义 |
---|---|
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-m | 如果调用到本地方法的话,可以显示C/C++的堆栈 |
-l | 除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况 |
输出某个进程的堆栈信息到文件中
jstack pid > filePath.tdump
堆信息
查看堆heap占用情况
root@5da1796872db:/# jps
7 jar
78 Jps
root@5da1796872db:/# jmap -heap pid
Attaching to process ID 7, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.342-b07
using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)
Heap Configuration: #堆内存初始化配置
MinHeapFreeRatio = 40 #-XX:MinHeapFreeRatio设置JVM堆最小空闲比率
MaxHeapFreeRatio = 70 #-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率
MaxHeapSize = 12620660736 (12036.0MB) #-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize = 1363144 (1.2999954223632812MB) #-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize = 7570718720 (7220.0MB) #-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize = 5452592 (5.1999969482421875MB) #-XX:OldSize=设置JVM堆的‘老生代’的大小
NewRatio = 2 #-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
MetaspaceSize = 21807104 (20.796875MB) # metaspace,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm(永久代)
CompressedClassSpaceSize = 1073741824 (1024.0MB) #-XX:CompressedClassSpaceSize=设置Klass Metaspace的大小
MaxMetaspaceSize = 17592186044415 MB #用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。
G1HeapRegionSize = 2097152 (2.0MB) #-XX:G1HeapRegionSize=n,使用G1时Java堆会被分为大小统一的的区(region)。此参数可以指定每个heap区的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32Mb.
Heap Usage: #堆使用
G1 Heap:
regions = 6018
capacity = 12620660736 (12036.0MB)#总容量
used = 413138944 (394.0MB)#使用情况
free = 12207521792 (11642.0MB)#剩余容量
3.2735127949484877% used
G1 Young Generation:
Eden Space: #Eden区内存分布
regions = 133
capacity = 463470592 (442.0MB)
used = 278921216 (266.0MB)
free = 184549376 (176.0MB)
60.18099547511312% used
Survivor Space:
regions = 17
capacity = 35651584 (34.0MB)
used = 35651584 (34.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 48
capacity = 291504128 (278.0MB)
used = 98566144 (94.0MB)
free = 192937984 (184.0MB)
33.81294964028777% used
37180 interned Strings occupying 3797384 bytes.
查看对象占用内存情况
root@5da1796872db:/# jmap -histo:live pid
num #instances #bytes class name
----------------------------------------------
1: 459904 33413656 [C
2: 459531 11028744 java.lang.String
3: 159580 9371824 [Ljava.lang.Object;
4: 66395 5842760 java.lang.reflect.Method
5: 117564 4702560 java.util.LinkedHashMap$Entry
6: 179720 4313280 java.util.ArrayList
7: 17027 4310544 [B
8: 122972 3935104 java.util.concurrent.ConcurrentHashMap$Node
9: 201016 3216256 org.apache.ibatis.scripting.xmltags.StaticTextSqlNode
10: 27718 2548264 [Ljava.util.HashMap$Node;
11: 48242 2315616 org.aspectj.weaver.reflect.ShadowMatchImpl
12: 96131 2307144 org.apache.ibatis.scripting.xmltags.IfSqlNode
13: 33433 1872248 java.util.LinkedHashMap
14: 116751 1868016 org.apache.ibatis.scripting.xmltags.MixedSqlNode
15: 16306 1824360 java.lang.Class
16: 97719 1563504 org.apache.ibatis.scripting.xmltags.ExpressionEvaluator
17: 21490 1547280 java.lang.reflect.Field
18: 48242 1543744 org.aspectj.weaver.patterns.ExposedState
19: 37631 1204192 java.util.HashMap$Node
20: 374 1055616 [Ljava.util.concurrent.ConcurrentHashMap$Node;
21: 42278 1014672 java.util.Collections$UnmodifiableRandomAccessList
22: 42587 946424 [Ljava.lang.Class;
23: 17466 838368 java.util.HashMap
24: 6770 649920 org.apache.ibatis.mapping.MappedStatement
25: 12001 474064 [I
26: 27212 435392 java.lang.Object
......
5992: 1 16 top.doudou.mybatis.plus.druid.RemoveDruidAdConfig$1
5993: 1 16 top.doudou.mybatis.plus.interceptor.MybatisInterceptor
Total 2900421 117573528
输出内容部分说明
- [C is a char[]
- [S is a short[]
- [I is a int[]
- [B is a byte[]
- [I is a int[][]
上面的输出中[C对象占用Heap这么多,往往跟String有关,String其内部使用final char[]数组来保存数据的。
导出堆信息
root@5da1796872db:/# jmap -dump:live,format=b,file=fileName.dmp pid
Dumping heap to /fileName.dmp ...
Heap dump file created
GC
类加载统计
root@5da1796872db:/# jstat -class pid
Loaded Bytes Unloaded Bytes Time
15292 29156.0 0 0.0 11.70
表头 | Loaded | Bytes | Unloaded | Bytes | Time |
---|---|---|---|---|---|
含义 | 加载class的数量 | 所占用空间大小 | 未加载数量 | 未加载占用空间 | 时间 |
编译统计
root@5da1796872db:/# jstat -compiler pid count
Compiled Failed Invalid Time FailedType FailedMethod
9935 1 0 57.95 1 org/springframework/util/ReflectionUtils doWithMethods
表头 | Compiled | Failed | Invalid | Time | FailedType | FailedMethod |
---|---|---|---|---|---|---|
含义 | 编译数量 | 失败数量 | 不可用数量 | 时间 | 失败类型 | 失败的方法 |
垃圾回收统计
root@5da1796872db:/# jstat -gc pid 2000 2
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
0.0 0.0 0.0 0.0 235520.0 2048.0 147456.0 114817.9 91508.0 87653.0 10952.0 10279.4 22 1.447 1 3.097 4.544
0.0 0.0 0.0 0.0 235520.0 2048.0 147456.0 114817.9 91508.0 87653.0 10952.0 10279.4 22 1.447 1 3.097 4.544
pid后面的2000表示2s,有这个参数则是,每隔2s返回一次数据,没有则只是查询当时数据,最后一个参数表示采样数目
末尾为C,代表该区Capacity(容量)
末尾为U,代表Used(已使用的容量)
表头 | S0C | S1C | S0U | S1U | EC | EU | OC | OU | MC | MU | YGC | YGCT | FGC | FGCT |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
含义 | Survive0 第一个幸存区的容量大小 | Survive1 第二个幸存区的容量大小 | Survive0 第一个幸存区已使用的内存大小 | Survive1 第二个幸存区已使用的内存大小 | Eden 伊甸园区的容量大小 | Eden 伊甸园区已使用的内存大小 | Old 老年代的容量大小 | Old 老年代已使用的内存大小 | Meta 方法区的容量大小 | Meta 方法区已使用的内存大小 | Young GC发生的次数 | Young GC的总耗时 | Full GC发生的次数 | Full GC的总耗时 |
堆内存统计
root@5da1796872db:/# jstat -gccapacity 7 2000 2
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
0.0 12324864.0 235520.0 0.0 0.0 235520.0 0.0 12324864.0 147456.0 147456.0 0.0 1130496.0 91508.0 0.0 1048576.0 10952.0 22 1
0.0 12324864.0 235520.0 0.0 0.0 235520.0 0.0 12324864.0 147456.0 147456.0 0.0 1130496.0 91508.0 0.0 1048576.0 10952.0 22 1
表头 | NGCMN | NGCMX | NGC | S0C | S1C | EC | OGCMN | OGCMX | OGC | OC | MCMN | MCMX | MC | CCSMN | CCSMX | CCSC | YGC | FGC |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
含义 | 新生代最小容量 | 新生代最大容量 | 当前新生代容量 | 第一个幸存区大小 | 第二个幸存区的大小 | 伊甸园区的大小 | 老年代最小容量 | 老年代最大容量 | 当前老年代大小 | 当前老年代大小 | 最小元数据容量 | 最大元数据容量 | 当前元数据空间大小 | 最小压缩类空间大小 | 最大压缩类空间大小 | 当前压缩类空间大小 | 年轻代gc次数 | 老年代GC次数 |
新生代垃圾回收统计
root@5da1796872db:/# jstat -gcnew 7 2000 2
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
0.0 0.0 0.0 0.0 6 15 29696.0 235520.0 2048.0 22 1.447
0.0 0.0 0.0 0.0 6 15 29696.0 235520.0 2048.0 22 1.447
表头 | S0C | S1C | S0U | S1U | TT | MTT | DSS | EC | EU | YGC | YGCT |
---|---|---|---|---|---|---|---|---|---|---|---|
含义 | 第一个幸存区大小 | 第二个幸存区的大小 | 第一个幸存区的使用大小 | 第二个幸存区的使用大小 | 对象在新生代存活的次数 | 对象在新生代存活的最大次数 | 期望的幸存区大小 | 伊甸园区的大小 | 伊甸园区的使用大小 | 年轻代垃圾回收次数 | 年轻代垃圾回收消耗时间 |
新生代内存统计
root@5da1796872db:/# jstat -gcnewcapacity 7 2000 2
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
0.0 12324864.0 235520.0 0.0 0.0 12324864.0 0.0 12324864.0 235520.0 22 1
0.0 12324864.0 235520.0 0.0 0.0 12324864.0 0.0 12324864.0 235520.0 22 1
表头 | NGCMN | NGCMX | NGC | S0CMX | S0C | S1CMX | S1C | ECMX | EC | YGC | FGC |
---|---|---|---|---|---|---|---|---|---|---|---|
含义 | 新生代最小容量 | 新生代最大容量 | 当前新生代容量 | 最大幸存1区大小 | 当前幸存1区大小 | 最大幸存2区大小 | 当前幸存2区大小 | 最大伊甸园区大小 | 当前伊甸园区大小 | 年轻代垃圾回收次数 | 老年代回收次数 |
老年代垃圾回收统计
root@b163e5a030ff:/# jstat -gcold 7 2000 2
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
87808.0 83909.2 10496.0 9793.6 284672.0 94208.0 22 0 0.000 1.047
87808.0 83909.2 10496.0 9793.6 284672.0 94208.0 22 0 0.000 1.047
表头 | MC | MU | CCSC | CCSU | OC | OU | YGC | FGC | FGCT | GCT |
---|---|---|---|---|---|---|---|---|---|---|
含义 | 方法区大小 | 方法区使用大小 | 压缩类空间大小 | 压缩类空间使用大小 | 老年代大小 | 老年代使用大小 | 年轻代垃圾回收次数 | 老年代垃圾回收次数 | 老年代垃圾回收消耗时间 | 垃圾回收消耗总时间 |
老年代内存统计
root@b163e5a030ff:/# jstat -gcoldcapacity 7 2000 2
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
0.0 12324864.0 284672.0 284672.0 22 0 0.000 1.047
0.0 12324864.0 284672.0 284672.0 22 0 0.000 1.047
表头 | OGCMN | OGCMX | OGC | OC | YGC | FGC | FGCT | GCT |
---|---|---|---|---|---|---|---|---|
含义 | 老年代最小容量 | 老年代最大容量 | 当前老年代大小 | 老年代大小 | 年轻代垃圾回收次数 | 老年代垃圾回收次数 | 老年代垃圾回收消耗时间 | 垃圾回收消耗总时间 |
元数据空间统计
root@b163e5a030ff:/# jstat -gcmetacapacity 7 2000 2
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1126400.0 87808.0 0.0 1048576.0 10496.0 22 0 0.000 1.047
0.0 1126400.0 87808.0 0.0 1048576.0 10496.0 22 0 0.000 1.047
表头 | MCMN | MCMX | MC | CCSMN | CCSMX | CCSC | YGC | FGC | FGCT | GCT |
---|---|---|---|---|---|---|---|---|---|---|
含义 | 最小元数据容量 | 最大元数据容量 | 当前元数据空间大小 | 最小压缩类空间大小 | 最大压缩类空间大小 | 当前压缩类空间大小 | 年轻代垃圾回收次数 | 老年代垃圾回收次数 | 老年代垃圾回收消耗时间 | 垃圾回收消耗总时间 |
总结垃圾回收统计
root@b163e5a030ff:/# jstat -gcutil 7 2000 2
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 100.00 53.64 33.09 95.56 93.31 22 1.047 0 0.000 1.047
0.00 100.00 53.64 33.09 95.56 93.31 22 1.047 0 0.000 1.047
表头 | S0 | S1 | E | O | M | CCS | YGC | FGC | FGCT | GCT |
---|---|---|---|---|---|---|---|---|---|---|
含义 | 幸存1区当前使用比例 | 幸存2区当前使用比例 | 伊甸园区使用比例 | 老年代使用比例 | 元数据区使用比例 | 压缩使用比例 | 年轻代垃圾回收次数 | 老年代垃圾回收次数 | 老年代垃圾回收消耗时间 | 垃圾回收消耗总时间 |
JVM编译方法统计
root@b163e5a030ff:/# jstat -printcompilation 7 2000 2
Compiled Size Type Method
10763 1652 1 org/springframework/cloud/openfeign/clientconfig/HttpClientFeignConfiguration$1 run
10763 1652 1 org/springframework/cloud/openfeign/clientconfig/HttpClientFeignConfiguration$1 run
表头 | Compiled | Size | Type | Method |
---|---|---|---|---|
含义 | 最近编译方法的数量 | 最近编译方法的字节码数量 | 最近编译方法的编译类型 | 方法名标识 |
docker设置G1垃圾回收器参数
以下任意一种方式即可
dockerfile的方式
......
ENV JAVA_OPTS=" -server -XX:SurvivorRatio=8 -XX:+DisableExplicitGC \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 -XX:SoftRefLRUPolicyMSPerMB=1000 -XX:+HeapDumpOnOutOfMemoryError \
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms512m -Xmx1024m \
-XX:NewRatio=3 -XX:+PrintGC -XX:+PrintGCDetails \
-XX:+PrintTenuringDistribution -XX:+PrintGCTimeStamps -XX:+PrintCommandLineFlags"
ENTRYPOINT java ${JAVA_OPTS} -Dspring.profiles.active=test -Djava.security.egd=file:/dev/./urandom -jar /app.jar
Docker Compose的方式
version: "3.5"
services:
xxx-server:
image: xxx
environment:
- JAVA_OPTS=-Xmx30m -Xms512m -Xss1024k
常用的几个参数设置
- -Xms512m:设置JVM初始堆内存为512m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
- -Xmx1024m:设置JVM最大堆内存为1024m。
- -Xss1024k:设置每个线程的栈大小。JDK5.0以后每个线程栈大小为1M,之前每个线程栈大小为256K。应当根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。需要注意的是:当这个值被设置的较大(例如>2MB)时将会在很大程度上降低系统的性能。
- -Xmn2g:设置年轻代大小为2G。在整个堆内存大小确定的情况下,增大年轻代将会减小年老代,反之亦然。此值关系到JVM垃圾回收,对系统性能影响较大,官方推荐配置为整个堆大小的3/8。
- -XX:NewSize=1024m:设置年轻代初始值为1024M。
- -XX:MaxNewSize=1024m:设置年轻代最大值为1024M。
- -XX:PermSize=256m:设置持久代初始值为256M。
- -XX:MaxPermSize=256m:设置持久代最大值为256M。
- -XX:NewRatio=4:设置年轻代(包括1个Eden和2个Survivor区)与年老代的比值。表示年轻代比年老代为1:4。
- -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的比值。表示2个Survivor区(JVM堆内存年轻代中默认有2个大小相等的Survivor区)与1个Eden区的比值为2:4,即1个Survivor区占整个年轻代大小的1/6。
- -XX:MaxTenuringThreshold=7:表示一个对象如果在Survivor区(救助空间)移动了7次还没有被垃圾回收就进入年老代。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代,对于需要大量常驻内存的应用,这样做可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代存活时间,增加对象在年轻代被垃圾回收的概率,减少Full GC的频率,这样做可以在某种程度上提高服务稳定性。
查看java的默认垃圾收集器
C:\Users\anjingsi>java -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=10 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=265781120 -XX:MaxHeapSize=4252497920 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
java version "14.0.2" 2020-07-14
Java(TM) SE Runtime Environment (build 14.0.2+12-46)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)
查看jvm的垃圾收集器
root@5da1796872db:/# jmap -heap pid
Attaching to process ID 7, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.342-b07
using thread-local object allocation.
Garbage-First *(G1) GC* with 4 thread(s)
docker开启ptrace
官网链接:https://docs.docker.com/engine/reference/run/
方式一
关闭seccomp,在启动容器时添加参数–security-opt seccomp=unconfined
docker run --security-opt seccomp:unconfined ...
方式二
启动容器时添加参数–cap-add=SYS_PTRACE
docker run --cap-add=SYS_PTRACE ...
Docker Compose的更改方式
version: "3.5"
services:
xxx-server:
image: xxx
cap_add:
- SYS_PTRACE
......
注意:本文归作者所有,未经作者允许,不得转载