1. 描述

​ 程序在开发过程中,有可能会发生CPU飙高、内存溢出等问题或系统在后期调优阶段,不可避免的要监控JVM情况,JDK自带的Jconsole监控工具,结合Tomcat使用非常方便,占用内存小,满足必要的监控项,还有不错的可视化界面,居家必备。

java线程的6种状态

初始态(NEW)

创建一个Thread对象,但还未调用start()启动线程时,线程处于初始态。

运行态(RUNNABLE),在Java中,运行态包括 就绪态 和 运行态。

就绪态

该状态下的线程已经获得执行所需的所有资源,只要CPU分配执行权就能运行。

所有就绪态的线程存放在就绪队列中。

运行态

获得CPU执行权,正在执行的线程。

由于一个CPU同一时刻只能执行一条线程,因此每个CPU每个时刻只有一条运行态的线程。

阻塞态(BLOCKED)

当一条正在执行的线程请求某一资源失败时,就会进入阻塞态。

而在Java中,阻塞态专指请求锁失败时进入的状态。

由一个阻塞队列存放所有阻塞态的线程。

处于阻塞态的线程会不断请求资源,一旦请求成功,就会进入就绪队列,等待执行。

等待态(WAITING)

当前线程中调用wait、join、park函数时,当前线程就会进入等待态。

也有一个等待队列存放所有等待态的线程。

线程处于等待态表示它需要等待其他线程的指示才能继续运行。

进入等待态的线程会释放CPU执行权,并释放资源(如:锁)

超时等待态(TIMED_WAITING)

当运行中的线程调用sleep(time)、wait、join、parkNanos、parkUntil时,就会进入该状态;它和等待态一样,并不是因为请求不到资源,而是主动进入,并且进入后需要其他线程唤醒;

进入该状态后释放CPU执行权 和 占有的资源。

与等待态的区别:到了超时时间后自动进入阻塞队列,开始竞争锁。

终止态(TERMINATED)

线程执行结束后的状态。

2. 方案

2.1 jconsole介绍

jconsole是JDK自带的工具,在JDK的bin下面有,本人系统的目录是:C:\Program Files\Java\jdk1.8.0_171\bin,进入目录双击:jconsole.exe,或者在cmd下执行都行,双击就会弹出下面的界面。

2.2 jconsole本地启动

​ 本地一般是在IDE开发工具(idea、ecplise),直接选择”本地进程“,双击对应进程就行了,其中名称为启动JVM名称,pid是进程号,例如我选择的是:com.hbusy.Application,双击进入监控页面。

​ jconsole控制台包含6个页面,分别为:概览、内存、线程、类、VM概要、MBean

2.2.1 概览

2.2.2 内存页面,可以查看jvm不同区占用的内存。

2.2.3 线程

2.2.4 类

2.2.5 VM 概要

2.2.6 Mbean

2.3 jconsole远程访问

2.3.1 参数配置

本人远程服务器是linux+tomcat,需要在tomcat的apache-tomcat-8.0.53/bin的catalina.sh 增加参数配置

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19107 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.0.11"

重点就两个参数:

(1) hostname设置为服务器ip地址;

(2) port访问端口号

2.3.2 jconsole远程访问

选择远程进程,然后输入访问地址:192.168.0.11:19107,进入后jconsol控制台后与本地访问控制台界面一样。

JDK自带的工具

在JDK的bin目录下有很多命令行工具:

  我们可以看到各个工具的大小基本上都稳定在27kb左右,这个不是JDK开发团队刻意为之的,而是因为这些工具大多数是jdk\lib\tools.jar类库的一层薄包装而已,他们的主要功能代码是在tools类库中实现的。命令行工具的好处是:当应用程序部署到生产环境后,无论是直接接触物理服务器还是远程telnet到服务器上都会受到限制。而借助tools.jar类库里面的接口,我们可以直接在应用程序中实现功能强大的监控分析功能。

常用命令:

这里主要介绍如下几个工具:

1、jps:查看本机java进程信息

2、jstack:打印线程的信息,制作 线程dump文件

3、jmap:打印内存映射信息,制作 堆dump文件

4、jstat:性能监控工具

5、jhat:内存分析工具,用于解析堆dump文件并以适合人阅读的方式展示出来

6、jconsole:简易的JVM可视化工具

7、jvisualvm:功能更强大的JVM可视化工具

8、javap:查看字节码

JAVA Dump:

JAVA Dump就是虚拟机运行时的快照,将虚拟机运行时的状态和信息保存到文件中,包括:

线程dump:包含所有线程的运行状态,纯文本格式

堆dump:包含所有堆对象的状态,二进制格式

1、jps

显示当前所有java进程pid的命令,我们可以通过这个命令来查看到底启动了几个java进程(因为每一个java程序都会独占一个java虚拟机实例),不过jps有个缺点是只能显示当前用户的进程id,要显示其他用户的还只能用linux的ps命令。

执行jps命令,会列出所有正在运行的java进程,其中jps命令也是一个java程序。前面的数字就是进程的id,这个id的作用非常大,后面会有相关介绍。

jps -help:

jps -l 输出应用程序main.class的完整package名或者应用程序jar文件完整路径名

jps -v 输出传递给JVM的参数

jps失效

我们在定位问题过程会遇到这样一种情况,用jps查看不到进程id,用ps -ef | grep java却能看到启动的java进程。

要解释这种现象,先来了解下jps的实现机制:

java程序启动后,会在目录/tmp/hsperfdata_{userName}/下生成几个文件,文件名就是java进程的pid,因此jps列出进程id就是把这个目录下的文件名列一下而已,至于系统参数,则是读取文件中的内容。

我们来思考下:如果由于磁盘满了,无法创建这些文件,或者用户对这些文件没有读的权限。又或者因为某种原因这些文件或者目录被清除,出现以上这些情况,就会导致jps命令失效。

如果jps命令失效,而我们又要获取pid,还可以使用以下两种方法:

1、top | grep java

2、ps -ef |grep java

2、jstack

主要用于生成指定进程当前时刻的线程快照,线程快照是当前java虚拟机每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致长时间等待。

3、jmap

主要用于打印指定java进程的共享对象内存映射或堆内存细节。

堆Dump是反映堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。一般在内存不足,GC异常等情况下,我们会去怀疑内存泄漏,这个时候就会去打印堆Dump。

jmap的用法摘要:

1、jmap pid

打印的信息分别为:共享对象的起始地址、映射大小、共享对象路径的全程。

2、jmap -heap pid:查看堆使用情况

3、jmap -histo pid:查看堆中对象数量和大小

打印的信息分别是:序列号、对象的数量、这些对象的内存占用大小、这些对象所属的类的全限定名

如果是内部类,类名的开头会加上*,如果加上live子参数的话,如jmap -histo:live pid,这个命名会触发一次FUll GC,只统计存活对象

4、jmap -dump:format=b,file=heapdump pid:将内存使用的详细情况输出到文件

然后使用jhat命令查看该文件:jhat -port 4000 文件名 ,在浏览器中访问http:localhost:4000/

总结:

该命令适用的场景是程序内存不足或者GC频繁,这时候很可能是内存泄漏。通过用以上命令查看堆使用情况、大量对象被持续引用等情况。

4、jstat

主要是对java应用程序的资源和性能进行实时的命令行监控,包括了对heap size和垃圾回收状况的监控。

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

option:我们经常使用的选项有gc、gcutil

vmid:java进程id

interval:间隔时间,单位为毫秒

count:打印次数

1、jstat -gc PID 5000 20

S0C:年轻代第一个survivor的容量(字节)

S1C:年轻代第二个survivor的容量(字节)

S0U:年轻代第一个survivor已使用的容量(字节)

S1U:年轻代第二个survivor已使用的容量(字节)

EC:年轻代中Eden的空间(字节)

EU:年代代中Eden已使用的空间(字节)

OC:老年代的容量(字节)

OU:老年代中已使用的空间(字节)

PC:永久代的容量

PU:永久代已使用的容量

YGC:从应用程序启动到采样时年轻代中GC的次数

YGCT:从应用程序启动到采样时年轻代中GC所使用的时间(单位:S)

FGC:从应用程序启动到采样时老年代中GC(FULL GC)的次数

FGCT:从应用程序启动到采样时老年代中GC所使用的时间(单位:S)

2、jstat -gcutil PID 5000 20

s0:年轻代中第一个survivor已使用的占当前容量百分比

s1:年轻代中第二个survivor已使用的占当前容量百分比

E:年轻代中Eden已使用的占当前容量百分比

O:老年代中已使用的占当前容量百分比

P:永久代中已使用的占当前容量百分比

5、jhat

主要用来解析java堆dump并启动一个web服务器,然后就可以在浏览器中查看堆的dump文件了。

生成dump文件的方法前面已经介绍了,这边主要介绍如何解析java堆转储文件,并启动一个web server

jhat heapdump

这个命令将heapdump文件转换成html格式,并且启动一个http服务,默认端口为7000。

如果端口冲突,可以使用以下命令指定端口:jhat -port 4000 heapdump

下面我们来访问下:ip:port

6、jinfo

jinfo可以用来查看正在运行的java运用程序的扩展参数,甚至支持在运行时动态地更改部分参数。

基本使用语法如下: jinfo -< option > < pid > ,其中option可以为以下信息:

-flag< name >: 打印指定java虚拟机的参数值

-flag [+|-]< name >:设置或取消指定java虚拟机参数的布尔值

-flag < name >=< value >:设置指定java虚拟机的参数的值

使用示例

下面的命令显示了新生代对象晋升到老年代对象的最大年龄。在运行程序运行时并没有指定这个参数,但是通过jinfo,可以查看这个参数的当前的值。

下面的命令显示是否打印gc详细信息:

下面的命令在运用程序运行时动态打开打印详细gc信息开关:

注意事项:jinfo虽然可以在java程序运行时动态地修改虚拟机参数,但并不是所有的参数都支持动态修改。

7、jcmd

在JDK 1.7之后,新增了一个命令行工具jcmd。它是一个多功能工具,可以用来导出堆,查看java进程,导出线程信息,执行GC等。jcmd拥有jmap的大部分功能,Oracle官方建议使用jcmd代替jmap。

使用 jcmd -l 命令列出当前运行的所有虚拟机,示例:

针对每一个虚拟机,可以使用help命令列出该虚拟机支持的所有命令,示例:

子命令含义:

  • VM.native_memory
  • VM.commercial_features
  • GC.rotate_log
  • ManagementAgent.stop
  • ManagementAgent.start_local
  • ManagementAgent.start
  • Thread.print,                         打印线程栈信息
  • GC.class_histogram,              查看系统中类统计信息
  • GC.heap_dump,                    导出堆信息,与jmap -dump功能一样
  • GC.run_finalization,               触发finalize()
  • GC.run,                                触发gc()
  • VM.uptime,                           VM启动时间
  • VM.flags,                              获取JVM启动参数
  • VM.system_properties,          获取系统Properties
  • VM.command_line,                 启动时命令行指定的参数
  • VM.version
  • help

示例:

8、可视化监控工具(JConsole、JVisualVM)

集上面之大成,并提供了可视化的界面;还可以监控远程Java服务;支持监控JMX。

JVisualVM比JConsole更强大:支持对CPU、内存运行进行采样、配置。推荐用JVisualVM。

JConsole监控页面示例:

JVisualVM监控页面示例:

JVM监控工具使用的更多相关文章

  1. JVM监控工具介绍

    JVM监控工具介绍 VisualVM是一种集成了多个JDK命令行工具的可视化工具,它能为您提供强大的分析能力.所有这些都是免费的!它囊括的命令行工具包括jps,jstat,jmap,jinfo,jst ...

  2. jvm 监控工具

    背景 不懂jvm监控工具好意思说自己搞java的吗.其实搞了十多年的人我都见过不懂得,不懂不要紧,老实工作就行啊.这就是属于非技术的话题了,实在不知从何说起.还是赶紧学习下吧,可以去装了.我认真学习后 ...

  3. Java之JVM监控工具分享

    Java之JVM监控工具分享 JVM的基本知识常用的也就是类加载机制,内存区域.分配.OOM,GC,JVM参数调优 几个链接自己看: 内存区域&类加载机制 分配策略&垃圾回收算法.收集 ...

  4. Java内存泄露监控工具:JVM监控工具介绍

    本文将对JVM监控工具jstack, jconsole, jinfo, jmap, jdb, jstat进行详细的介绍,具体内容请看下文 Sun JDK监控和故障处理工具 名称 主要作用 jps JV ...

  5. Java JVM监控工具JConsole简介

    Java JVM监控工具JConsole简介 jconsole命令 功能:打开java监视管理控制台 方法: jconsole [选项1] [选项2] …… [选项n] 常用选项: -help     ...

  6. JVM 监控工具 jstack 和 jvisualvm 的使用

    Java线程状态 线程的五种状态 * 新建:new(时间很短) * 运行:runnable * 等待:waitting(无限期等待),timed waitting(限期等待) * 阻塞:blocked ...

  7. 常见JVM监控工具用法介绍

    VisualVM是一种集成了多个JDK命令行工具的可视化工具,它能为您提供强大的分析能力.所有这些都是免费的!它囊括的命令行工具包括jps,jstat,jmap,jinfo,jstack,JConso ...

  8. JVM监控工具用法指导

    JVM监控工具用法指导 2010-09-27 15:39 dolphin-ygj javaeye.com 字号:T | T 通过JVM监控工具的使用可以及时发现问题,剔除安全隐患,这里向大家描述一下常 ...

  9. Java线程及Jvm监控工具

    Java线程状态 线程的五种状态 * 新建:new(时间很短) * 运行:runnable * 等待:waitting(无限期等待),timed waitting(限期等待) * 阻塞:blocked ...

  10. JVM 监控工具——jps

    [参考文章]:[Linux运维入门]Jstatd方式远程监控Linux下 JVM运行情况 1. jps简介 显示系统内所有的HotSpot虚拟机进程. 且只能查看当前用户下的Java进程信息: 2. ...

随机推荐

  1. 【填算符】(log 值域的做法)

    比赛在这里呢 填算符 下发题解说的神马东西,赛时根本想不到 讲一个赛时想得到的 \(O(n\log 值域)\) 的思路,很好理解 我们处理出二进制下每一位上的 1 的最后一次出现的位置,将第 \(i\ ...

  2. MarkDown用法学习笔记

    标题: 用 '#'标识,可以到从1到6级标题设置,有多少个'#'符号就对应多少级标题 粗体: 用''标识,如果两边只有一个''标识是斜体,如果两有2个这符号标题是加粗,如果有3个这符号标识是斜体和加粗 ...

  3. 如何获取Flume连接HDFS所需要的包

    在学习Hadoop工具中的Flume时,有的小伙伴会遇到这句话: "Flume要想将数据输出到HDFS,必须持有Hadoop相关jar包" 然后小伙伴就懵逼了,这些包要去什么地方来 ...

  4. 鸿蒙NEXT开发案例:转盘

    [1]引言(完整代码在最后面) 在鸿蒙NEXT系统中,开发一个有趣且实用的转盘应用不仅可以提升用户体验,还能展示鸿蒙系统的强大功能.本文将详细介绍如何使用鸿蒙NEXT系统开发一个转盘应用,涵盖从组件定 ...

  5. OpenGL编程指南(原书第9版)

    这本书是<OpenGL编程指南(原书第9版)>,也称为<OpenGL Programming Guide: The Official Guide to Learning OpenGL ...

  6. HTTP相关返回值异常如何解决(下篇)

    ​ 今天我们讲讲HTTP相关返回值异常如何解决(实例持续更新中) 一.4xx客户端错误状态码  这些状态码表示请求有问题,通常是由于客户端的错误引起的. 1.1 400 Bad Request: 请求 ...

  7. Python脚本消费多个Kafka topic

    在Python中消费多个Kafka topic,可以使用kafka-python库,这是一个流行的Kafka客户端库.以下是一个详细的代码示例,展示如何创建一个Kafka消费者,并同时消费多个Kafk ...

  8. 自定义 MySQL Shell 提示符

    MySQL Shell 中的提示符的样式和格式可以根据使用者的需求进行定制.我们可以配置提示符以显示有关数据库连接和使用的模式的不同或简化信息.本文将展示如何添加视觉提示,让您知道何时连接到生产数据库 ...

  9. 设置 crossdomain.xml 文件实施 HTTP 流式传输

    本文概括介绍了跨域策略文件,以及如何在 Adobe Media Server 中为 HTTP 流式传输配置该文件. 为什么需要采用 crossdomain.xml 文件? 跨域策略文件 跨域策略文件是 ...

  10. golang之操作kafka

    安装第三方包: go get github.com/IBM/sarama 生产者实例: package main import ( "fmt" "github.com/I ...