top
- up
系统运行时间 - user
当前登录用户数 - load average
系统负载
单核100%负载的值为1,如若四核100%负载,其值为4。
后面的三个数值分别表示系统过去1分钟、5分钟、15分钟内运行进程队列中的平均进程数量。 - Tasks
当前进程总数,其中running、sleeping、stopped、zombie分别对应当前运行进程数,睡眠进程数,停止进程数,僵尸进程数 - %Cpu(s)
us: user cpu time (or) % CPU time spent in user space
sy: system cpu time (or) % CPU time spent in kernel space
ni: user nice cpu time (or) % CPU time spent on low priority processes
id: idle cpu time (or) % CPU time spent idle
wa: io wait cpu time (or) % CPU time spent in wait (on disk)
hi: hardware irq (or) % CPU time spent servicing/handling hardware interrupts
si: software irq (or) % CPU time spent servicing/handling software interrupts
st: steal time - - % CPU time in involuntary wait by virtual cpu while hypervisor is servicing another processor (or) % CPU time stolen from a virtual machine - Mem
内存总容量 使用的物理内存总量 空闲内存总量 用做内核缓存的内存量; - Swap
交换分区总量 使用的交换分区总量 空闲的交换分区总量 缓冲的交换区总量
proc
proc文件系统是一个虚拟的文件系统,不占用磁盘空间,它反映了当前操作系统在内存中的运行情况,查看/proc下的文件可以了解到系统的运行状态。查看系统平均负载使用“cat /proc/loadavg”命令。
其值分别为1分钟内的平均进程数, 5分钟内的平均进程数, 15分钟内的平均进程数, 正在运行的进程数/进程总数, 最近运行的进程号。
jps
jps主要用来输出JVM中运行的进程状态信息。语法格式如下:
jps [options] [hostid]
命令行参数选项说明如下:
-q 不输出类名、Jar名和传入main方法的参数
-m 输出传入main方法的参数
-l 输出main类或Jar的全限名
-v 输出传入JVM的参数
jvm中的常用命令
一些常用命令
jstat -gcutil -t -h5 18165 1000 10
jmap -histo:live 18165 | more 简单查看对象的大小数目
top
jmap -heap18165
jmap -histo:live 18165 | grep com.upsmart.processor
导出整个JVM 中内存信息
jmap -dump:format=b,file=文件名 [pid]
jstack 是sun JDK 自带的工具,通过该工具可以看到JVM 中线程的运行状况,包括锁等待,线程是否在运行
执行 jstack [pid] ,线程的所有堆栈信息
jstack 18165|more
gc回收日志分析
参考博客:https://www.cnblogs.com/zhangxiaoguang/p/5792468.html 整理
示例分析:
JAVA_OPTS=
J
A
V
A
O
P
T
S
"
−
s
e
r
v
e
r
−
D
t
o
m
c
a
t
.
s
e
r
v
e
r
.
p
o
r
t
=
8005
−
D
t
o
m
c
a
t
.
h
t
t
p
.
p
o
r
t
=
8080
−
D
t
o
m
c
a
t
.
i
n
s
t
a
n
c
e
.
n
a
m
e
=
b
i
d
d
i
n
g
s
e
r
v
e
r
"
J
A
V
A
O
P
T
S
=
JAVA_OPTS" -server -Dtomcat.server.port=8005 -Dtomcat.http.port=8080 -Dtomcat.instance.name=bidding_server" JAVA_OPTS=
JAVAOPTS"−server−Dtomcat.server.port=8005−Dtomcat.http.port=8080−Dtomcat.instance.name=biddingserver"JAVAOPTS=JAVA_OPTS" -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=256m"
JAVA_OPTS=
J
A
V
A
O
P
T
S
"
−
X
X
:
+
U
s
e
P
a
r
N
e
w
G
C
−
X
X
:
+
C
M
S
P
a
r
a
l
l
e
l
R
e
m
a
r
k
E
n
a
b
l
e
d
−
X
X
:
+
U
s
e
C
o
n
c
M
a
r
k
S
w
e
e
p
G
C
−
X
X
:
C
M
S
I
n
i
t
i
a
t
i
n
g
O
c
c
u
p
a
n
c
y
F
r
a
c
t
i
o
n
=
75
"
J
A
V
A
O
P
T
S
=
JAVA_OPTS" -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75" JAVA_OPTS=
JAVAOPTS"−XX:+UseParNewGC−XX:+CMSParallelRemarkEnabled−XX:+UseConcMarkSweepGC−XX:CMSInitiatingOccupancyFraction=75"JAVAOPTS=JAVA_OPTS" -Xloggc:
C
A
T
A
L
I
N
A
B
A
S
E
/
l
o
g
s
/
g
c
.
l
o
g
−
X
X
:
+
P
r
i
n
t
G
C
D
e
t
a
i
l
s
−
X
X
:
+
P
r
i
n
t
G
C
D
a
t
e
S
t
a
m
p
s
"
J
A
V
A
O
P
T
S
=
CATALINA_BASE/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" JAVA_OPTS=
CATALINABASE/logs/gc.log−XX:+PrintGCDetails−XX:+PrintGCDateStamps"JAVAOPTS=JAVA_OPTS" -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
C
A
T
A
L
I
N
A
B
A
S
E
/
l
o
g
s
/
h
e
a
p
d
u
m
p
.
h
p
r
o
f
"
J
A
V
A
O
P
T
S
=
CATALINA_BASE/logs/heapdump.hprof" JAVA_OPTS=
CATALINABASE/logs/heapdump.hprof"JAVAOPTS=JAVA_OPTS" -Duser.timezone=GMT+08"
export JAVA_OPTS
日志分析:
- CMS-initial-mark:
这是CMS中两次stop-the-world事件中的一次。它有两个目标:一是标记老年代中所有的GC Roots;二是标记被年轻代中活着的对象引用的对象。
2018-11-11T18:04:44.830+0800: 1294214.256: GC事件开始,包括时钟时间和相对JVM启动时候的相对时间,下边所有的阶段改时间的含义相同;[GC [1 CMS-initial-mark: 1305711K 当前老年代使用情况(1415616K老年代可用容量)] 1419764K 当前整个堆的使用情况
(2029056K 整个堆的容量), 0.0233270 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] - CMS-concurrent-mark:
这个阶段会遍历整个老年代并且标记所有存活的对象,从“初始化标记”阶段找到的GC Roots开始。并发标记的特点是和应用程序线程同时运行。并不是老年代的所有存活对象都会被标记,因为标记的同时应用程序会改变一些对象的引用等。
在上边的图中,一个引用的箭头已经远离了当前对象(current obj)
2018-11-11T18:04:45.703+0800: 1294215.130: [CMS-concurrent-mark: 0.802/0.828 secs 展示该阶段持续的时间和时钟时间] [Times: user=2.99 sys=0.28, real=0.82 secs] - CMS-concurrent-preclean:
这个阶段又是一个并发阶段,和应用线程并行运行,不会中断他们。前一个阶段在并行运行的时候,一些对象的引用已经发生了变化,当这些引用发生变化的时候,JVM会标记堆的这个区域为Dirty Card(包含被标记但是改变了的对象,被认为"dirty"),这就是 Card Marking。
在pre-clean阶段,那些能够从dirty card对象到达的对象也会被标记,这个标记做完之后,dirty card标记就会被清除了,如下:
另外,一些必要的清扫工作也会做,还会做一些final remark阶段需要的准备工作;
2018-11-11T18:04:45.728+0800: 1294215.154: [CMS-concurrent-preclean: 0.020/0.024 secs] [Times: user=0.04 sys=0.01, real=0.03 secs] - CMS-concurrent-abortable-preclean:
又一个并发阶段不会停止应用程序线程。这个阶段尝试着去承担STW的Final Remark阶段足够多的工作。这个阶段持续的时间依赖好多的因素,由于这个阶段是重复的做相同的事情直到发生aboart的条件(比如:重复的次数、多少量的工作、持续的时间等等)之一才会停止。
2018-11-11T18:04:47.992+0800: 1294217.419: [CMS-concurrent-abortable-preclean: 2.194/2.265 secs] [Times: user=4.20 sys=0.37, real=2.26 secs]
这个阶段很大程度的影响着即将来临的Final Remark的停顿,有相当一部分重要的 configuration options 和 失败的模式;
Final Remark ??此阶段日志存疑
这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象。由于之前的预处理是并发的,它可能跟不上应用程序改变的速度,这个时候,STW是非常需要的来完成这个严酷考验的阶段。
通常CMS尽量运行Final Remark阶段在年轻代是足够干净的时候,目的是消除紧接着的连续的几个STW阶段。
2018-11-11T18:04:47.994+0800: 1294217.420: [GC[YG occupancy: 475153 K (613440 K)]2018-11-11T18:04:47.994+0800: 1294217.421: [Rescan (parallel) , 0.0753090 secs]2018-11-11T18:04:48.069+0800: 1294217.496: [weak refs processing, 0.0000810 secs]2018-11-11T18:04:48.069+0800: 1294217.496: [scrub string table, 0.0353080 secs] [1 CMS-remark: 1328587K(1415616K)] 1803740K(2029056K), 0.1108570 secs] [Times: user=0.63 sys=0.00, real=0.11 secs] - Concurrent Sweep
和应用线程同时进行,不需要STW。这个阶段的目的就是移除那些不用的对象,回收他们占用的空间并且为将来使用。
2018-11-11T18:04:54.658+0800: 1294224.084: [GC2018-11-11T18:04:54.658+0800: 1294224.084: [ParNew: 613440K->613440K(613440K), 0.0000280 secs]2018-11-11T18:04:54.658+0800: 1294224.084: [CMS2018-11-11T18:04:55.144+0800: 1294224.570: [CMS-concurrent-mark: 0.746/0.749 secs] [Times: user=1.94 sys=0.04, real=0.74 secs]
(concurrent mode failure): 1313336K->1331651K(1415616K), 3.2322730 secs] 1926776K->1331651K(2029056K), [CMS Perm : 129566K->129566K(262144K)], 3.2325250 secs] [Times: user=3.72 sys=0.00, real=3.23 secs]
这段信息显示ParNew 收集器被请求进行新生代的回收,但收集器并没有尝试回收,因为 它 预计在最糟糕的情况下, CMS 老年代中没有足够的空间容纳新生代的幸存对象。我们把这个失败称之为”完全晋升担保失败”。
因为这样,并发模式的 CMS 被中断同并且在 1294224.570秒时,Full GC被启动。这次Full GC,采用标记-清除-整理算法,会发生stop-the-world,费时3.2325250秒。CMS 老年代占用从 402978K 降到248977K。??? - Concurrent Reset
这个阶段并发执行,重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用。
2018-11-12T10:00:09.650+0800: 32.174: [CMS-concurrent-reset: 0.003/0.003 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
top及free命令的解疑
参考博客:https://blog.csdn.net/yinchunhui_222/article/details/25992957
Used接近total
很疑惑到底为什么,开始怀疑是内存泄露,但是服务已经全部杀掉后used仍然保持很高。
查询了下linux下使用top命令进行监控的详细解释,网上对这个的解释很多很详细,实际上并非服务内存泄露的原因,而是linux内核对于内存的管理造成的:
-
linux中内核对于已经使用了的内存,当期被服务或应用释放掉后,未必会将其放在free中,而是可能将其放在buffers和cached中
-
top中显示的men中 used free 实际上都是内核角度的内存分配情况 也就是虽然used 使用很高 但是实际上服务或者应用是可以使用buffers和cached的内存的
当top中看到的free不多了的时候,内核会从buffers和cached中吐一部分出来支援free
3.可以使用 free命令进行进一步的查看:截图上有
图中可见:
buffer/cache 中的used 实际上才是实际被使用的内存大小,而其下的free 12053476是实际服务/应用可用的内存,mem与top中的mem是一样的,也就是mem中的free+buffers+cached(1416704+61736+10575136=12053476)才是buffer/cache中的 free(12053476)
后续压测中也验证了这一点,当mem中free较多时,优先使用free的实际物理内存,buffers和cached基本不变,当free快要耗尽时,buffers和cached变小,free会增加一些。
当然,如果buffers和cached也耗尽了,系统就会使用swap虚拟内存。
综上,linux系统下进行top检测内存的使用情况,不能完全看mem中的used 和 free 还是需要结合 free -m 和实际的应用进行具体分析。