排查问题一些常用命令总结 —— 主要针对java程序

top

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”命令。
proc命令
其值分别为1分钟内的平均进程数, 5分钟内的平均进程数, 15分钟内的平均进程数, 正在运行的进程数/进程总数, 最近运行的进程号。

jps

jps主要用来输出JVM中运行的进程状态信息。语法格式如下:
jps [options] [hostid]
命令行参数选项说明如下:
-q 不输出类名、Jar名和传入main方法的参数
-m 输出传入main方法的参数
-l 输出main类或Jar的全限名
-v 输出传入JVM的参数
jps命令jps-v图片

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 整理
示例分析
jvm配置文件
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"serverDtomcat.server.port=8005Dtomcat.http.port=8080Dtomcat.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:+UseParNewGCXX:+CMSParallelRemarkEnabledXX:+UseConcMarkSweepGCXX: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.logXX:+PrintGCDetailsXX:+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

日志分析
gc日志

  • 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
Top及free命令截图分析Used接近total
很疑惑到底为什么,开始怀疑是内存泄露,但是服务已经全部杀掉后used仍然保持很高。

查询了下linux下使用top命令进行监控的详细解释,网上对这个的解释很多很详细,实际上并非服务内存泄露的原因,而是linux内核对于内存的管理造成的:

  1. linux中内核对于已经使用了的内存,当期被服务或应用释放掉后,未必会将其放在free中,而是可能将其放在buffers和cached中

  2. 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 和实际的应用进行具体分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值