深入理解JAVA虚拟机第四章(常用工具使用汇总)

小热身

  • 查看java进程24544的gc实时情况 ,每隔5s钟,一共10次

    jstat -gcutil 24544 5000 10

  • 查看该进程GC的原因

    jstat -gccause 24544

  • 查看该进程内存使用情况

    jmap -heap 24544

  • 查看该进程的对象使用内存情况

    jmap -histo 21689

  • dump该进程当前的对象使用内存情况(二进制文件)并通过Java VisualVM查看

    jmap -dump:live,format=b,file=heap.bin 24544
    然后将 heap.bin sz到本地(假设线上环境
    打开jvisualvm 在这里插入图片描述
    在这里插入图片描述

  • 通过Jconsole远程动态查看该ES进程内存以及各线程对象运行的实时情况
    • 首先暴露ES进程的JMX,具体如下:
    • 编辑 /root/elasticsearch-2.4.4/bin/elasticsearch
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.xx.xx -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9100 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
           jmx需要指定hostname,和CentOS的houstname保持一致。

在这里插入图片描述

  • 重启该节点
  • 在本地打开JConsole,填写ip 端口(9100), 账号密码。
    在这里插入图片描述

jstack

  • jstack是什么

    jstack是JVM自带的堆栈跟踪工具,用于打印出给定的java进程ID堆栈信息快照。Java线程的类型有以下两种:用户自定义线程和JVM自身线程(如GC)。

  • 线程的状态

    • NEW:线程刚被创建,但是还没有被处理(不会出现在Dump中)
    • RUNNABLE:线程占用了 CPU 并且处理了一个任务。(或是是在等待状态由于操作系统的资源分配)
    • BLOCKED:该线程正在等待另外的不同的线程释放锁,以便获取监视器锁
    • WAITING:该线程正在等待,通过使用了 wait, join 或者是 park 方法
    • TIMED_WAITING:有时限的线程等待,通过使用了 sleep, wait, join 或者是 park 方法。(这个与 WAITING 不同是通过方法参数指定了最大等待时间,WAITING 可以通过时间或者是外部的变化解除)
    • TERMINATED: 已退出的。
  • Thread Dump中的线程修饰

    表示线程在方法调用时,额外的重要的操作。线程 Dump 分析的重要信息。修饰上方的方法调用。

    • locked <地址> 目标:使用 synchronized 申请对象锁成功,监视器的拥有者。
    • waiting to lock <地址> 目标:使用 synchronized 申请对象锁未成功,在迚入区等待。
    • waiting on <地址> 目标:使用 synchronized 申请对象锁成功后,释放锁幵在等待区等待。
    • parking to wait for <地址> 目标
    • waiting for monitor entry:等待进入一个临界区(如synchronized)
    • waiting on condition:等待另一个条件的发生来把自己唤醒
    • in Object.wait():获得Monitor之后,调用wait()方法
    • runnable:该状态表示线程具备所有运行条件,在运行队列中准备操作系统的调度,或者正在运行
  • Thread Dump文件的线程信息

    (1) 如下为执行jstack pid获取的某个线程的信息:

“pool-1-thread-1” #10 prio=5 os_prio=0 tid=0x00000000203c7000 nid=0x38820 waiting for monitor entry [0x0000000020caf000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.ly.test.Example.doTask(Example.java:30)
- waiting to lock <0x000000076b4e4d10> (a java.lang.Object)
at com.ly.test.Example.lambda$startUp 0 ( E x a m p l e . j a v a : 21 ) a t c o m . l y . t e s t . E x a m p l e 0(Example.java:21) at com.ly.test.Example 0(Example.java:21)atcom.ly.test.Example$Lambda 1 / 245257410. r u n ( U n k n o w n S o u r c e ) a t j a v a . u t i l . c o n c u r r e n t . E x e c u t o r s 1/245257410.run(Unknown Source) at java.util.concurrent.Executors 1/245257410.run(UnknownSource)atjava.util.concurrent.ExecutorsRunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

  • pool-1-thread-1:线程名字
    prio=5:优先级
    nid=0x38820:线程ID的十六进制(可通过线程ID获取该线程的CPU和内存的使用情况,可以通过top -H -p pid查看,然后再转换成16进制)
    waiting for monitor entry:线程修饰状态
    0x0000000020caf000:线程的调用栈信息

(2)线程死锁

“Thread-1”:
at com.dxz.jstack.EasyJstackResource.read(EasyJstackResource.java:36)
- waiting to lock <0x00000000d7149440> (a com.dxz.jstack.EasyJstackResource R e s o u r c e ) − l o c k e d < 0 x 00000000 d 7149428 > ( a c o m . d x z . j s t a c k . E a s y J s t a c k R e s o u r c e Resource) - locked <0x00000000d7149428> (a com.dxz.jstack.EasyJstackResource Resource)locked<0x00000000d7149428>(acom.dxz.jstack.EasyJstackResourceResource)
at com.dxz.jstack.EasyJstack.run(EasyJstack.java:41)
“Thread-0”:
at com.dxz.jstack.EasyJstackResource.write(EasyJstackResource.java:46)
- waiting to lock <0x00000000d7149428> (a com.dxz.jstack.EasyJstackResource R e s o u r c e ) − l o c k e d < 0 x 00000000 d 7149440 > ( a c o m . d x z . j s t a c k . E a s y J s t a c k R e s o u r c e Resource) - locked <0x00000000d7149440> (a com.dxz.jstack.EasyJstackResource Resource)locked<0x00000000d7149440>(acom.dxz.jstack.EasyJstackResourceResource)
at com.dxz.jstack.EasyJstack.run(EasyJstack.java:42)

Found 1 deadlock.
Thread-1持有对象<0x00000000d7149428>,并且尝试获取<0x00000000d7149440>Thread-0持有对象<0x00000000d7149440>,并且尝试获取<0x00000000d7149428>,最后两个线程都处于阻塞状态,造成死锁。

(3)排查CPU占用高的进程

    a.如果大量线程在"waiting for monitor entry"

          可能是一个全局锁阻塞了大量的线程。如果短时间内打印的 thread dump 文件反映,随着时间流逝,waiting for monitor entry 的线程越来越多,没有减少的趋势,可能意味着某些线程在临界区里呆的时间太长了,以至于越来越多新线程迟迟无法进入临界区。

    b.如果大量线程在"waiting on condition":

          可能是它们又跑去获取第三方资源,尤其是第三方网络资源,迟迟获取不到Response,导致大量线程进入等待状态。所以如果你发现有大量的线程都处在 Wait on condition,从线程堆栈看,正等待网络读写,这可能是一个网络瓶颈的征兆,因为网络阻塞导致线程无法执行。

Jmap( *** 代表进程号

生成堆转储快照

  • 查看该进程下堆内存的使用情况
    jmap -heap ***

  • 快速定位内存泄露的方法:
    jmap -histo:live ***

  • 可以使用jhat分析内存溢出的原因
    使用dump内存信息到heap.bin文件
    jmap -dump:live,format=b,file=heap.bin ***

在这里插入图片描述

  • jstat 监视垃圾回收(GC)时间,次数

    jstat -gcutil ***

S0: 幸存区0
S1: 幸存区1
E:年轻代
O:年老代
M:持久代
(以上都是已使用所占百分比)
YGC : 年轻代YGC的次数
YGCT :年轻代YGC所消耗的时间
FGC : 年老代full GC的次数
FGCT :年老代full GC所消耗的时间
GCT : 用于GC所消耗的总时间

  • jstat动态查看垃圾回收的情况:

    jstat -gcutil *** 2000 5

    注:2秒搜集显示一次 显示5次 退出

Jhat

分析JMap对存储快照,和JMap配合使用

  • 使用jhat 对heap.bin 文件进行分析
    jhat -J-mx512m heap.bin 如果解析过程中出现内存不足,需要加大内存如:jhat -J-mx812m heap.bin
    在这里插入图片描述
    再通过浏览器访问 http://localhost:7000/ 即可看到分析结果

    展示的信息较多,比如此对象被谁引用,又引用了哪个,所以没有那么清晰明了

Jstat

jstat的主要是用来查看GC情况和Heap Size资源使用情况。

  • jstat命令格式
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

参数解释:
option 常见的都是使用-gcutil查看gc情况,其他可选项见下图。
vmid : VM的进程号,即当前运行的java进程号。
interval : 间隔时间,单位为秒或毫秒
count:打印次数,如果缺省则打印无数次。
option选项代表着用户希望查询的虚拟机信息,主要分为3类:类加载、垃圾收集和运行期编译状况。 在这里插入图片描述

参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。

  • 假设需要每250毫秒查询一次进程5828垃圾收集状况,一共查询5次,那命令行如下:

jstat -gc 5828 250 5

  • 垃圾回收统计
    查看所有gc的统计信息,分代信息统计使用-gcnew,-gcold

jstat -gcutil 31798

运行截图:

在这里插入图片描述
参数含义:

S0 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
s1 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E 年轻代中Eden已使用的占当前容量百分比
O old代已使用的占当前容量百分比
M 元空间(MetaspaceSize)已使用的占当前容量百分比
CCS 压缩使用比例
YGC 年轻代垃圾回收次数
FGC 老年代垃圾回收次数
FGCT 老年代垃圾回收消耗时间
GCT 垃圾回收消耗总时间
堆内存使用情况统计
查看所有内存使用情况,分代信息统计使用-gcnewcapacity,-gcoldcapacity,-gcmetacapacity,单位KB。

  • jstat -gccapacity 3400 20 20

运行截图:

在这里插入图片描述

NGCMN 新生代最小容量
NGCMX 新生代最大容量
NGC 当前新生代容量
S0C 第一个幸存区大小
S1C 第二个幸存区的大小
EC 伊甸园区的大小
OGCMN 老年代最小容量
OGCMX 老年代最大容量
OGC 当前老年代大小
OC 当前老年代大小
MCMN 最小元数据容量
MCMX 最大元数据容量
MC 当前元数据空间大小
CCSMN 最小压缩类空间大小
CCSMX 最大压缩类空间大小
CCSC 当前压缩类空间大小
YGC 年轻代gc次数
FGC 老年代GC次数

JConsole

JVM监视和管理平台

windows下打开路径:在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值