jstack、jstat和jmap等是jdk自带的内存分析工具,能够帮助我们分析堆、内存、线程的运行状况等。
jstack
1)查看线程的栈信息,即JVM的当前时刻的线程快照。
2)主要用于定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部时长过长导致线程停顿的原因。
3)建议间隔一定时间采集一次,通过3-5次采集,确认是否有线程一直处于running状态,方便定位是否出现第2点的情况
用法:
jstack <PID>
jstack <PID> > test.txt #输出到文件
例如:
[root@root-36-70 ~]# jstack 7574
2022-08-03 12:00:46
Full thread dump Java HotSpot™ 64-Bit Server VM (25.211-b12 mixed mode):
“Keep-Alive-Timer” #304 daemon prio=8 os_prio=0 tid=0x00007fd3a4002800 nid=0x7a30 waiting on condition [0x00007fd4282e1000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:172)
at java.lang.Thread.run(Thread.java:748)
“com.alibaba.nacos.client.Worker.longPolling.fixed-172.16.36.150_8848” #75 daemon prio=5 os_prio=0 tid=0x00007fd39c001000 nid=0x4d4f waiting on condition [0x00007fd4233f4000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007028dc008> (a java.util.concurrent.locks.AbstractQueuedSynchronizer
C
o
n
d
i
t
i
o
n
O
b
j
e
c
t
)
a
t
j
a
v
a
.
u
t
i
l
.
c
o
n
c
u
r
r
e
n
t
.
l
o
c
k
s
.
L
o
c
k
S
u
p
p
o
r
t
.
p
a
r
k
(
L
o
c
k
S
u
p
p
o
r
t
.
j
a
v
a
:
175
)
a
t
j
a
v
a
.
u
t
i
l
.
c
o
n
c
u
r
r
e
n
t
.
l
o
c
k
s
.
A
b
s
t
r
a
c
t
Q
u
e
u
e
d
S
y
n
c
h
r
o
n
i
z
e
r
ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer
ConditionObject)atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:175)atjava.util.concurrent.locks.AbstractQueuedSynchronizerConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor
D
e
l
a
y
e
d
W
o
r
k
Q
u
e
u
e
.
t
a
k
e
(
S
c
h
e
d
u
l
e
d
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
.
j
a
v
a
:
1081
)
a
t
j
a
v
a
.
u
t
i
l
.
c
o
n
c
u
r
r
e
n
t
.
S
c
h
e
d
u
l
e
d
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081) at java.util.concurrent.ScheduledThreadPoolExecutor
DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)atjava.util.concurrent.ScheduledThreadPoolExecutorDelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
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)
Thread.State描述
状态/动作 描述
New 当线程对象创建时存在的状态,此时线程不可能执行
Runnable 当调用thread.start()后,线程变成为Runnable状态, 也就是就绪状态。只要得到CPU,就可以执行
Running 线程正在执行
Waiting 执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己
Timed_Waiting 执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制
Dead 线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束
Deadlock 表示有死锁
stat
1)主要用于统计堆内存、类相关和GC相关信息
2)可以时时监控资源和性能
用法:
jstat -gc <pid>
jstat -gc <pid> 2s 100 #间隔2s连续输出100次
例如:
[root@lsy-36-70 ~]# jstat -gc 7574 2s 10
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
149760.0 149760.0 35129.5 0.0 749056.0 746427.7 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 35129.5 0.0 749056.0 746540.0 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 35129.5 0.0 749056.0 746687.8 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 35129.5 0.0 749056.0 746731.0 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 35129.5 0.0 749056.0 746745.0 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 35129.5 0.0 749056.0 746878.8 1048576.0 222899.5 129280.0 122844.9 15104.0 14076.8 152 8.696 0 0.000 8.696
149760.0 149760.0 0.0 24516.0 749056.0 3428.4 1048576.0 223104.6 129280.0 122850.1 15104.0 14076.8 153 8.720 0 0.000 8.720
149760.0 149760.0 0.0 24516.0 749056.0 3670.3 1048576.0 223104.6 129280.0 122850.1 15104.0 14076.8 153 8.720 0 0.000 8.720
149760.0 149760.0 0.0 24516.0 749056.0 3734.9 1048576.0 223104.6 129280.0 122850.1 15104.0 14076.8 153 8.720 0 0.000 8.720
149760.0 149760.0 0.0 24516.0 749056.0 3881.1 1048576.0 223104.6 129280.0 122850.1 15104.0 14076.8 153
各指标描述:
S0C:年轻代中第一个survivor(幸存区)的容量 (字节 Capacity)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节 Used)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
MC:metaspace(元空间)的容量 (字节)
MU:metaspace(元空间)目前已使用空间 (字节)
CCSC:当前压缩类空间的容量 (字节)
CCSU:当前压缩类空间目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
jmap
1)查看堆内存信息,包括使用的GC算法、堆配置参数和各代中堆内存使用情况,可以结合jhat使用
2)主要用于分析OOM
用法:
jmap -heap <PID>
jmap -dump:format=b,file=HeapDump <pid> #dump出内存信息,可用内存分析工具分析情况,format=b是通过二进制的意思
例如:
1)直接查看堆内存信息
[root@lsy-36-70 ~]# jmap -heap 7574
Attaching to process ID 7574, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.211-b12
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 3183476736 (3036.0MB)
NewSize = 66060288 (63.0MB)
MaxNewSize = 1061158912 (1012.0MB)
OldSize = 133169152 (127.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 562561024 (536.5MB)
used = 386173616 (368.2838592529297MB)
free = 176387408 (168.2161407470703MB)
68.64564012170172% used
From Space:
capacity = 1048576 (1.0MB)
used = 720896 (0.6875MB)
free = 327680 (0.3125MB)
68.75% used
To Space:
capacity = 14155776 (13.5MB)
used = 0 (0.0MB)
free = 14155776 (13.5MB)
0.0% used
PS Old Generation
capacity = 108003328 (103.0MB)
used = 27321200 (26.055526733398438MB)
free = 80682128 (76.94447326660156MB)
25.296627896503338% used
16408 interned Strings occupying 1561208 bytes.
2)dump出堆内存信息到文件
[root@lsy-36-70 ~]# jmap -dump:format=b,file=/tmp/dump01.dat 7574
Dumping heap to /tmp/dump01.dat ...
Heap dump file created
3)jhat查看,浏览器输入7000端口访问
[root@lsy-36-70 ~]# jhat -port 7000 /tmp/dump01.dat