jps:查看正在运行的Java进程

jps(Java Process Status):显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。
说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。

  1. jps [options] [hostid]

查看命令相关参数:jps -h或者jps -help
image.png
我们还可以通过追加参数,来打印额外的信息。

  • options参数

    • -q:仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等
    • -l:输出应用程序主类的全类名 或 如果进程执行的是jar包,则输出jar完整路径
    • -m:输出虚拟机进程启动时传递给主类main()的参数
    • -v:列出虚拟机进程启动时的JVM参数。比如:-Xms20m -Xmx50m是启动程序指定的jvm参数。

      以上参数可以多个一起使用。 如果某 Java 进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该Java 进程。

  • hostid参数

    • 就是输入ip和port进行远程主机的监控查看,需要安装 jstatd
    • 不安全

      jstat:查看JVM统计信息

      jstat(JVM Statistics Monitoring Tool):用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。
      1. jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
      查看命令相关参数:jstat -hjstat -help

      vmid表示jjava程序进程id

  • option参数

    • 选项option可以由以下值构成。
    • 类装载相关的
      • **-class**:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等
        • image.png
          • Loaded:加载类的个数
          • Bytes:加载类占用的字节数
          • Unloaded:卸载类的个数
          • Bytes:卸载类占用的字节数
          • Time:花费的总体时间
    • 垃圾回收相关的
      • **-gc**:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。
        • image.png
          • S开头的是幸存者0和1区
          • C结尾是总容量
          • U结尾是已经使用的容量
          • E开头是伊甸园区
          • O开头是老年区
          • M开头是方法区
          • CCS开头是压缩类
          • GC结尾表示垃圾回收的次数
          • T结尾表示GC花费的时间
          • Y开头年轻代GC
          • F开头FullGC
      • **-gccapacity**:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
        • image.png
      • **-gcutil**:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
        • image.png
      • **-gccause**:与-gcutil功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。
        • image.png
      • **-gcnew**:显示新生代GC状况
        • image.png
      • **-gcnewcapacity**:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
        • image.png
      • **-gcold**:显示老年代GC状况
        • image.png
      • **-gcoldcapacity**:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
        • image.png
    • JIT相关的
      • **-compiler**:显示JIT编译器编译过的方法、耗时等信息
        • image.png
      • **-printcompilation**:输出已经被JIT编译的方法
        • image.png

  • interval参数: 用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
    • image.png
  • count参数: 用于指定查询的总次数
    • image.png
  • -t参数: 可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
    • image.png
  • -h参数: 可以在周期性数据输出时,输出多少行数据后输出一个表头信息
    • image.png

经验

我们可以比较Java进程的启动时间以及总GC时间(GCT列),或者两次测量的间隔时间以及总GC时间的增量,来得出GC时间占运行时间的比例。 如果该比例超过20%,则说明目前堆的压力比较大,如果该比例超过90%,则说明堆里面几乎没有可用空间,随时可能抛出OOM异常。

:::warning 在长时间运行的Java程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中OU列(已使用的老年代的最小值)。
然后,我们每隔一段较长的时间重复一次上述的操作,来获得多组OU最小值。如果这些值呈现上涨趋势,则说明该Java程序的老年代内存正在使用量不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄露。 :::

jinfo:实时查看和修改JVM配置参数

jinfo(Configuration Info for Java):查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下,用jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。

  1. jinfo [options] pid

说明:java 进程ID必须要加上,就是pid

  • options参数
    • 没有参数:输出全部的参数和系统属性,很多
    • **-flag name**:输出对应名称的参数
      • image.png
    • **-flag [+-]name**:开启或者关闭对应名称的参数 只有被标记为manageable的参数才可以被动态修改
      • image.png
    • **-flag name=value**:设定对应名称的参数
      • image.png
    • **-flags**:输出全部的参数
      • image.png
    • **-sysprops**:输出系统属性
      • image.png

拓展

  • **java -XX:+PrintFlagsInitial**:查看所有JVM参数启动的初始值,很多
  • **java -XX:+PrintFlagsFinal**:查看所有JVM参数的最终值
  • **java -XX:+PrintCommandLineFlags**:查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值

    jmap:导出内存映像文件&内存使用情况

    jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。

    1. jmap [option] <pid>
    2. jmap [option] <executable <core>
    3. jmap [option] [server_id@] <remote server IP or hostname>

    查看命令相关参数:jmap -hjmap -help

  • option参数

    • **-dump**:生成dump文件(Java堆转储快照),-dump:live只保存堆中的存活对象

      1. #hprof是后缀名
      2. jmap -dump:format=b,file=<filename.hprof> <pid>
      3. jmap -dump:live,format=b,file=<filename.hprof> <pid>
      1. #在程序发生OOM时,导出应用程序当前堆快照
      2. -XX:+HeapDumpOnOutOfMemoryError
      3. #可以指定堆快照的保存位置
      4. -XX:HeapDumpPath=<filename.hprof>
    • **-heap**:输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等

    • **-histo**:输出堆空间中对象的统计信息,包括类、实例数量和合计容量,-histo:live只统计堆中的存活对象
    • **-J <flag>**:传递参数给jmap启动的jvm
    • **-finalizerinfo**:显示在F-Queue中等待Finalizer线程执行finalize方法的对象,仅linux/solaris平台有效
    • **-permstat**:以ClassLoader为统计口径输出永久代的内存状态信息,仅linux/solaris平台有效
    • **-F**:当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件,仅linux/solaris平台有效

由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。 举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。 另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,而jstat只需直接读取即可。

jhat:JDK自带堆分析工具

jhat(JVM Heap Analysis Tool):Sun JDK提供的jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。
使用了jhat命令,就启动了一个http服务,端口是7000,即http://localhost:7000/,就可以在浏览器里分析。
说明:jhat命令在JDK9、JDK10中已经被删除,官方建议用VisualVM代替。

  1. jhat <option> <dumpfile>
  • option参数
    • **-stack false|true**:关闭|打开对象分配调用栈跟踪
    • **-refs false|true**:关闭|打开对象引用跟踪
    • **-port port-number**:设置jhat HTTP Server的端口号,默认7000
    • **-exclude exclude-file**:执行对象查询时需要排除的数据成员
    • **-baseline exclude-file**:指定一个基准堆转储
    • **-debug int**:设置debug级别
    • **-version**:启动后显示版本信息就退出
    • **-J <flag>**:传入启动参数,比如-J-Xmx512m

      jstack:打印JVM中线程快照

      jstack(JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
      生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

      在thread dump中,要留意下面几种状态

      • 死锁,Deadlock(重点关注)
      • 等待资源,Waiting on condition(重点关注)
      • 等待获取监视器,Waiting on monitor entry(重点关注)
      • 阻塞,Blocked(重点关注)
      • 执行中,Runnable
      • 暂停,Suspended
      • 对象等待中,Object.wait() 或 TIMED_WAITING
      • 停止,Parked
  1. jstack <option> pid
  • option参数

    • **-F**:当正常输出的请求不被响应时,强制输出线程堆栈
    • **-l**:除堆栈外,显示关于锁的附加信息
    • **-m**:如果调用本地方法的话,可以显示C/C++的堆栈

      jcmd:多功能命令行

      在JDK 1.7以后,新增了一个命令行工具jcmd。它是一个多功能的工具,可以用来实现前面除了jstat之外所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。
      jcmd拥有jmap的大部分功能,并且在Oracle的官方网站上也推荐使用jcmd命令代jmap命令
  • jcmd -l:列出所有的JVM进程

  • jcmd 进程号 help:针对指定的进程,列出支持的所有具体命令
    • image.png
  • jcmd 进程号 具体命令:显示指定进程的指令命令的数据
    • Thread.print 可以替换 jstack指令
    • GC.class_histogram 可以替换 jmap中的-histo操作
    • GC.heap_dump 可以替换 jmap中的-dump操作
    • GC.run 可以查看GC的执行情况
    • VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的-t操作
    • VM.system_properties 可以替换 jinfo -sysprops 进程id
    • VM.flags 可以获取JVM的配置参数信息

      jstatd:远程主机信息收集

      之前的指令只涉及到监控本机的Java应用程序,而在这些工具中,一些监控工具也支持对远程计算机的监控(如jps、jstat)。为了启用远程监控,则需要配合使用jstatd 工具。命令jstatd是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的Java应用程序信息传递到远程计算机。