企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # jps显示java进程 `java process status` 命令格式:`jps [options] [hostid] ` `[options]`选项 : ~~~ -q:仅输出VM标识符,不包括classname,jar name,arguments in main method  -m:输出main method的参数  -l:输出完全的包名,应用主类名,jar的完全路径名  -v:输出jvm参数  -V:输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件  -Joption:传递参数到vm,例如:-J-Xms512m ~~~ ~~~ jps -lmv ~~~ # jstat分析JVM的使用情况 **jstat -gc** 例子 如下表示分析进程id为31736 的gc情况,每隔1000ms打印一次记录,打印10次停止,每3行后打印指标头部 ~~~ jstat -gc -h3 31736 1000 10 ~~~ | 参数 | 描述 | | --- | --- | | S0C |年轻代中第一个survivor(幸存区)的容量 (字节) | S1C |年轻代中第二个survivor(幸存区)的容量 (字节) | S0U |年轻代中第一个survivor(幸存区)目前已使用空间 (字节) | S1U |年轻代中第二个survivor(幸存区)目前已使用空间 (字节) | EC | 年轻代中Eden(伊甸园)的容量 (字节) | EU | 年轻代中Eden(伊甸园)目前已使用空间 (字节) | OC | Old代的容量 (字节) | OU | Old代目前已使用空间 (字节) | PC | Perm(持久代)的容量 (字节) | PU | Perm(持久代)目前已使用空间 (字节) | YGC |从应用程序启动到采样时年轻代中gc次数 | YGCT| 从应用程序启动到采样时年轻代中gc所用时间(s) | FGC |从应用程序启动到采样时old代(全gc)gc次数 | FGCT| 从应用程序启动到采样时old代(全gc)gc所用时间(s) | GCT |从应用程序启动到采样时gc用的总时间(s) **jstat -gcutil** 查看gc的统计信息 ~~~ jstat -gcutil xxxx ~~~ | 参数 | 描述 | | --- | --- | | S0 | 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 | S1 | 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 | E | 年轻代中Eden(伊甸园)已使用的占当前容量百分比 | O | old代已使用的占当前容量百分比 | P | perm代已使用的占当前容量百分比 | YGC | 从应用程序启动到采样时年轻代中gc次数 | YGCT| 从应用程序启动到采样时年轻代中gc所用时间(s) | FGC | 从应用程序启动到采样时old代(全gc)gc次数 | FGCT| 从应用程序启动到采样时old代(全gc)gc所用时间(s) | GCT | 从应用程序启动到采样时gc用的总时间(s) **`jstat -gccapacity pid`** 可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小, | 参数 | 描述 | | --- | --- | | NGCMN | 年轻代(young)中初始化(最小)的大小 (字节) | NGCMX | 年轻代(young)的最大容量 (字节) | NGC | 年轻代(young)中当前的容量 (字节) | S0C | 年轻代中第一个survivor(幸存区)的容量 (字节) | S1C |年轻代中第二个survivor(幸存区)的容量 (字节) | EC | 年轻代中Eden(伊甸园)的容量 (字节) | OGCMN | old代中初始化(最小)的大小 (字节) | OGCMX | old代的最大容量 (字节) | OGC | old代当前新生成的容量 (字节) | OC | Old代的容量 (字节) | PGCMN | perm代中初始化(最小)的大小 (字节) | PGCMX | perm代的最大容量 (字节) | PGC | perm代当前新生成的容量 (字节) | PC | Perm(持久代)的容量 (字节) | YGC | 从应用程序启动到采样时年轻代中gc次数 | FGC | 从应用程序启动到采样时old代(全gc)gc次数 # jinfo查看jvm扩展参数 ~~~ jinfo [option] <pid> jinfo [option] <executable <core> jinfo [option] [server_id@]<remote server IP or hostname> where <option> is one of: -flag <name> to print the value of the named VM flag -flag [+|-]<name> to enable or disable the named VM flag -flag <name>=<value> to set the named VM flag to the given value -flags to print VM flags -sysprops to print Java system properties <no option> to print both of the above ~~~ **参数说明** * pid 对应jvm的进程id * executable core 产生core dump文件 * \[server-id@\]remote server IP or hostname 远程的ip或者hostname,server-id标记服务的唯一性id **option** * no option 输出全部的参数和系统属性 * \-flag name 输出对应名称的参数 * \-flag \[+|-\]name 开启或者关闭对应名称的参数 * \-flag name=value 设定对应名称的参数 * \-flags 输出全部的参数 * \-sysprops 输出系统属性 **Javacore 概述** Javacore,也可以称为“threaddump”或是“javadump”,它是 Java 提供的一种诊断特性,能够提供一份可读的当前运行的 JVM 中线程使用情况的快照。即在某个特定时刻,JVM 中有哪些线程在运行,每个线程执行到哪一个类,哪一个方法。 应用程序如果出现不可恢复的错误或是内存泄露,就会自动触发 Javacore 的生成 > 命令:jinfo pid > 描述:输出当前 jvm 进程的全部参数和系统属性 > 命令:jinfo -flag name pid > 描述:输出对应名称的参数 > 可以查看指定的 jvm 参数的值。如:查看当前 jvm 进程是否开启打印 GC 日志。 > 命令:jinfo -flag \[+|-\]name pid > 描述:开启或者关闭对应名称的参数 > 使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用。主要是针对 boolean 值的参数设置的 > 命令:jinfo -flag name=value pid > 描述:修改指定参数的值。 > 如果是设置 value值,则需要使用 name=value 的形式。 > 命令:jinfo -flags pid > 描述:输出全部的参数 > 命令:jinfo -sysprops pid > 描述:输出当前 jvm 进行的全部的系统属性 # jmap生成堆内信息 命令jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。 ~~~ jmap [option] <pid> jmap [option] <executable <core> jmap [option] [server_id@]<remote server IP or hostname> ~~~ **参数** * **option:** 选项参数。 * **pid:** 需要打印配置信息的进程ID。 * **executable:** 产生核心dump的Java可执行文件。 * **core:** 需要打印配置信息的核心文件。 * **server-id** 可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。 * **remote server IP or hostname** 远程调试服务器的IP地址或主机名。 **option** * **no option:** 查看进程的内存映像信息,类似 Solaris pmap 命令。 * **heap:** 显示Java堆详细信息 * **histo\[:live\]:** 显示堆中对象的统计信息 * **clstats:**打印类加载器信息 * **finalizerinfo:** 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象 * **dump::**生成堆转储快照 * **F:** 当-dump没有响应时,使用-dump或者-histo参数. 在这个模式下,live子参数无效. * **help:**打印帮助信息 * **J:**指定传递给运行jmap的JVM的参数 >命令:jmap pid >描述:查看进程的内存映像信息,类似 Solaris pmap 命令。 > 使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。 > 命令:jmap -heap pid > 描述:显示Java堆详细信息 > 命令:jmap -dump:format=b,file=heapdump.phrof pid > 描述:生成堆转储快照dump文件。 > 以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。 这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用, 线上系统慎用。 # jcmd 一个多功能的工具,可以用它来导出堆、查看Java进程、导出线程信息、执行GC、还可以进行采样分析(jmc 工具的飞行记录器) **查看性能统计** 命令:`jcmd pid PerfCounter.print ` 描述:查看指定进程的性能统计信息 **列出当前运行的 java 进程可以执行的操作** 命令:`jcmd PID help` **查看具体命令的选项** 如果想查看命令的选项,比如想查看 JFR.dump 命令选项,可以通过如下命令: `jcmd 11772 help JFR.dump` **JFR** 要使用 JRF 相关的功能,必须使用 VM.unlock\_commercial\_features 参数取消锁定商业功能 ~~~ jcmd 8152 VM.unlock_commercial_features ~~~ * 启动JFR 执行命令:jcmd $PID JFR.start name=abc,duration=120s * Dump JFR 等待至少duration(本文设定120s)后,执行命令:jcmd PID JFR.dump name=abc,duration=120s filename=abc.jfr(注意,文件名必须为.jfr后缀) * 检查JFR状态 执行命令:jcmd $PID JFR.check name=abc,duration=120s * 停止JFR 执行命令:jcmd $PID JFR.stop name=abc,duration=120s * JMC分析 切回开发机器,下载步骤3中生成的abc.jfr,打开jmc,导入abc.jfr即可进行可视化分析 **查看 JVM 的启动时长** 命令:`jcmd PID VM.uptime` **查看系统中类统计信息** 命令:`jcmd PID GC.class_histogram` **查看目标jvm进程的版本信息** `jcmd PID VM.version` **执行gc** `jcmd PID GC.run ` **查看 JVM 的启动命令行** `jcmd PID VM.command_line` **查看 JVM 的启动参数** `jcmd PID VM.flags` # jhat分析堆文件 用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言 ~~~ jhat xxx ~~~ 有时你dump出来的堆很大,在启动时会报堆空间不足的错误,可以使用如下参数: `jhat -J-Xmx512m` # jstack线程堆栈分析 参数提示 * \-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent 的 ownable synchronizers列表. * \-F 当’jstack \[-l\] pid’没有相应的时候强制打印栈信息 * \-m 打印java和native c/c++框架的所有栈信息. 通过 jstack 命令可以获取当前进程的所有线程信息。 每个线程堆中信息中,都可以查看到 线程ID、线程的状态(wait、sleep、running 等状态)、是否持有锁信息等。 **Object.wait()情况** 一个线程处于WAITING状态,在Test.java文件13行处,正是我们调用wait方法的地方,说明该线程目前还没等到notify ![](https://img.kancloud.cn/f3/56/f356957d0a839c8a4b1e9c1adce624bf_775x226.png) **死锁** 可以清楚的看出 mythread2 等待 这个锁 “0x00000000d6eb82d0”,这个锁是由于mythread1线程持有。 mythread1线程等待这个锁“0x00000000d6eb8300”,这个锁是由mythread2线程持有。 ![](https://img.kancloud.cn/ec/a2/eca290cbf01b1476d1154acbe8ea19a6_1184x344.png) **等待IO** ![](https://img.kancloud.cn/19/12/19127f0ae2af4cd3a2239f190a613ecb_662x178.png) # mac,jmc界面问题 这个问题是由于Eclipse/SWT老版本的bug导致的,可以通过替换相关jar解决。bug reference: JMC-5139 1. 下载jar包:[下载地址](https://search.maven.org/search?q=g:org.eclipse.platform%20AND%20a:org.eclipse.swt.cocoa.macosx.x86_64&core=gavr)(选最上面的即可)。 2. 进入jdk安装目录,在lib/missioncontrol/plugins目录内找到org.eclipse.swt.cocoa.macosx.x86_64_3.103.1.v20140903-1947.jar,将其备份。 (通过安装包安装的jdk目录为/Library/Java/JavaVirtualMachines/jdk1.8.0_xxx.jdk/Contents/Home/) 3. 将我们下载的jar包重命名为org.eclipse.swt.cocoa.macosx.x86_64_3.103.1.v20140903-1947.jar,复制到lib/missioncontrol/plugins目录内替换原jar包。 重启jmc