6. JDK内置命令行工具

JDK自带的工具和程序分为2大类型:

  1. 开发工具
  2. 诊断分析工具

开发工具

工具简介
javaJava 应用的启动程序
javacJDK 内置的编译工具
javap反编译 class 文件的工具
javadoc根据 Java 代码和标准注释,自动生成相关的 API 说明文档
javahJNI 开发时,根据 Java 代码生成需要的 .h 文件。
extcheck检查某个 jar 文件和运行时扩展 jar 有没有版本冲突,很少使用
jdbJava Debugger 可以调试本地和远端程序,属于 JPDA 中的一个 Demo 实现,供其他调试器参考。开发时很少使用
jdeps探测 class 或 jar 包需要的依赖
jar打包工具,可以将文件和目录打包成为 .jar 文件;.jar 文件本质上就是 zip 文件,只是后缀不同。使用时按顺序对应好选项和参数即可。
keytool安全证书和密钥的管理工具(支持生成、导入、导出等操作)
jarsignerjar 文件签名和验证工具
policytool实际上这是一款图形界面工具,管理本机的 Java 安全策略

诊断分析工具

  • jps/jinfo:查看java进程
  • jstat:查看JVM内部gc相关
  • jmap:查看heap或类占用空间统计
  • jstack:查看线程信息
  • jcmd:执行JVM相关分析命令(整合命令)
  • jrunscript/jjs:执行js命令
JPS

linux中有ps命令展示进程运行情况,jps就是展示Java进程信息。JPS 展示的是当前用户可看见的 Java 进程。

❯ jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]
  • -q:只显示进程号。
  • -m:显示传给 main 方法的参数信息
  • -l:显示启动 class 的完整类名,或者启动 jar 的完整路径
  • -V:大写的 V,这个参数有问题,相当于没传一样。官方说的跟 -q 差不多。
  • <hostid>:部分是远程主机的标识符,需要远程主机启动 jstatd 服务器支持。

可以看到,格式为 <hostname>[:<port>],不能用 IP,示例:jps -v sample.com:1099

知道 JVM 进程的 PID 之后,就可以使用其他工具来进行诊断了。

一般直接使用jps或者jps -lmv这两个。

❯ jps
2432 Jps
13780
8824 Launcher
❯ jps -lmv
8560 com.zchi.itWorkSite.ItWorkSiteApplication -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:65306,suspend=y,server=n -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.output.ansi.enabled=always -javaagent:C:\Users\张弛\AppData\Local\JetBrains\IntelliJIdea2021.3\captureAgent\debugger-agent.jar -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=UTF-8
13780  exit -Xms128m -Xmx750m -XX:ReservedCodeCacheSize=512m -XX:+IgnoreUnrecognizedVMOptions -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=50 -XX:CICompilerCount=2 -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -ea -Dsun.io.useCanonCaches=false -Djdk.http.auth.tunneling.disabledSchemes="" -Djdk.attach.allowAttachSelf=true -Djdk.module.illegalAccess.silent=true -Dkotlinx.coroutines.debug=off -Xmx2048m -javaagent:D:\newIdea\filter-agent.jar -Djb.vmOptionsFile=C:\Users\张弛\AppData\Roaming\JetBrains\IntelliJIdea2021.3\idea64.exe.vmoptions -Djava.system.class.loader=com.intellij.util.lang.PathClassLoader -Didea.vendor.name=JetBrains -Didea.paths.selector=IntelliJIdea2021.3 -Didea.jre.check=true -Dsplash=true -Dide.native.launcher=true -XX:ErrorFile=C:\Users\ java_error_in_idea64_%p.log -XX:HeapDumpPath=C:\Users\ java_error_in_idea64.hprof
16488 sun.tools.jps.Jps -lmv -Denv.class.path=.;D:\jdk8\lib;D:\jdk8\lib\tools.jar -Dapplication.home=D:\jdk8 -Xms8m
21004 org.jetbrains.jps.cmdline.Launcher D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/jps-builders.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/jps-builders-6.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/jps-javac-extension-1.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/util.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/annotations.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/3rd-party-rt.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/jna.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/kotlin-stdlib-jdk8.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/protobuf.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/platform-api.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/jps-model.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/javac2.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/forms_rt.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/qdox.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/aether-dependency-resolver.jar;D:/newIdea/IntelliJ IDEA 2021.3/plugins/java/lib/3rd-party.jar;D:/newIdea/IntelliJ IDEA 2021.3/lib/idea_rt.jar;D:/newIdea/Intell -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Dpreload.project.path=D:/code/zchi/itWorkSite -Dpreload.config.path=C:/Users/张 弛/AppData/Roaming/JetBrains/IntelliJIdea2021.3/options -Dexternal.project.config=C:\Users\张弛\AppData\Local\JetBrains\IntelliJIdea2021.3\external_build_system\itworksite.3b46255f -Dcompile.parallel=true -Drebuild.on.dependency.change=true -Djdt.compiler.useSingleThread=true -Daether.connector.resumeDownloads=false -Dio.netty.initialSeedUniquifier=1631241794010994822 -Dfile.encoding=GBK -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2021.3 -Didea.home.path=D:/newIdea/IntelliJ IDEA 2021.3 -Didea.config.path=C:/Users/张弛/AppData/Roaming/JetBrains/IntelliJIdea2021.3 -Didea.plugins.path=C:/Users/张弛/AppData/Roaming/JetBrains/IntelliJIdea2021.3/plugins -Djps.log.dir=C:/Users/张弛/AppData/Local/JetBrains/IntelliJIdea2021.3/log/build-log -Djps.fallback.jdk.home=D:/newIdea/IntelliJ IDEA 2021.3/jbr -Djps.fallback.jdk.version=11.0.13 -Dio.netty.noUnsafe=tru
jinfo

jinfo 用来查看具体生效的配置信息以及系统属性,还支持动态增加一部分参数

查看帮助信息:

❯ jinfo            
Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

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
    -h | -help           to print this help message

不加参数过滤会打印所有的参数

❯ jinfo 8560  

看到所有的系统属性和启动使用的 VM 参数、命令行参数。非常有利于我们排查问题,特别是去排查一个已经运行的 JVM 里问题,通过 jinfo 我们就知道它依赖了哪些库,用了哪些参数启动。

如果在 Mac 和 Linux 系统上使用一直报错,则可能是没有权限,或者 jinfo 版本和目标 JVM 版本不一致的原因

jstat

用来监控 JVM 内置的各种统计信息,主要是内存和 GC 相关的信息。

❯ jstat -help
Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
  <option>      An option reported by the -options option
  <vmid>        Virtual Machine Identifier. A vmid takes the following form:
                     <lvmid>[@<hostname>[:<port>]]
                Where <lvmid> is the local vm identifier for the target
                Java virtual machine, typically a process id; <hostname> is
                the name of the host running the target Java virtual machine;
                and <port> is the port number for the rmiregistry on the
                target host. See the jvmstat documentation for a more complete
                description of the Virtual Machine Identifier.
  <lines>       Number of samples between header lines.
  <interval>    Sampling interval. The following forms are allowed:
                    <n>["ms"|"s"]
                Where <n> is an integer and the suffix specifies the units as 
                milliseconds("ms") or seconds("s"). The default units are "ms".
  <count>       Number of samples to take before terminating.
  -J<flag>      Pass <flag> directly to the runtime system.

支持的选项

❯ jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
  • -class:类加载(Class loader)信息统计。
  • -compiler:JIT 即时编译器相关的统计信息。
  • -gc:GC 相关的堆内存信息,用法:jstat -gc -h 10 -t 864 1s 20
  • -gccapacity:各个内存池分代空间的容量。
  • -gccause:看上次 GC、本次 GC(如果正在 GC 中)的原因,其他输出和 -gcutil 选项一致。
  • -gcnew:年轻代的统计信息(New = Young = Eden + S0 + S1)。
  • -gcnewcapacity:年轻代空间大小统计。
  • -gcold:老年代和元数据区的行为统计。
  • -gcoldcapacity:old 空间大小统计。
  • -gcmetacapacity:meta 区大小统计。
  • -gcutil:GC 相关区域的使用率(utilization)统计。
  • -printcompilation:打印 JVM 编译统计信息。
❯ jstat -class 8560
Loaded  Bytes  Unloaded  Bytes     Time   
 11529 20512.3        0     0.0      30.80

jstat -gc 8560截图
后缀的C表示容量(capacity),U表示使用(utilization),S表示存活区(Survivor)

  • S0C:0号存活区当前容量(capacity),单位kb
  • S1C:1号存活区当前容量,单位kb
  • S0U:0号存活区使用量(unilization),单位kb
  • S1U:1号存活区使用量,单位kb
  • EC:Eden区当前容量,单位kb
  • EU:Eden区使用量,单位kb
  • OC:Old区当前容量,单位kb
  • OU:Old区使用量,单位kb
  • MC:元数据区当前容量,单位kb
  • MU:元数据区使用量,单位kb
  • CCSC:压缩的class空间容量,单位kb
  • CCSU:压缩的class空间使用量,单位kb
  • YGC:Young GC的次数
  • YGCT:Yong GC的总耗时。重点关注
  • FGC:Full GC的次数。
  • FGCT:Full GC的总耗时。重点关注
  • GCT:GC总耗时。
jstat -gc 8560 1000 2

备注:1000毫秒统计一次,一共统计两次。

剩下的option都可以这样用,例如:

❯ jstat -gcutil 8560 1000 2
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00 100.00  68.12   3.60  94.17  92.20      8    0.128     0    0.000    0.128
  0.00 100.00  68.12   3.60  94.17  92.20      8    0.128     0    0.000    0.128
jmap

jmap 主要用来 Dump 堆内存。当然也支持输出统计信息。

官方推荐使用 JDK 8 自带的 jcmd 工具来取代 jmap,但是 jmap 深入人心,jcmd 可能暂时取代不了。

查看帮助信息:

❯ jmap -h
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

常用的3个选项:

  • -heap:打印堆内存(/内存池)的配置和使用信息。
  • -histo:看哪些类占用的空间最多,基本看不出什么。最大的[C表示chat[][B表示byte[][I表示int[]。
  • -dump:format=b,file=xxxx.hprof:Dump 堆内存。

查看堆内存统计信息

❯ jmap -heap 8560
Attaching to process ID 8560, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11

using thread-local object allocation.
Garbage-First (G1) GC with 13 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 8032092160 (7660.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 4819255296 (4596.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 7660
   capacity = 8032092160 (7660.0MB)
   used     = 259576000 (247.55096435546875MB)
   free     = 7772516160 (7412.449035644531MB)
   3.231735827094892% used
G1 Young Generation:
Eden Space:
   regions  = 216
   capacity = 315621376 (301.0MB)
   used     = 226492416 (216.0MB)
   free     = 89128960 (85.0MB)
   71.76079734219269% used
Survivor Space:
   regions  = 2
   capacity = 2097152 (2.0MB)
   used     = 2097152 (2.0MB)
   free     = 0 (0.0MB)
   100.0% used
G1 Old Generation:
   regions  = 31
   capacity = 185597952 (177.0MB)
   used     = 30986432 (29.55096435546875MB)
   free     = 154611520 (147.44903564453125MB)
   16.695460087835453% used

23089 interned Strings occupying 2187544 bytes.
jcmd

JDK 8 推出的一款本地诊断工具,只支持连接本机上同一个用户空间下的 JVM 进程。

查看帮助信息

❯ jcmd -h
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
   or: jcmd -l
   or: jcmd -h

  command must be a valid jcmd command for the selected jvm.
  Use the command "help" to see which commands are available.
  If the pid is 0, commands will be sent to all Java processes.
  The main class argument will be used to match (either partially
  or fully) the class used to start Java.
  If no options are given, lists Java processes (same as -p).

  PerfCounter.print display the counters exposed by this process
  -f  read and execute commands from the file
  -l  list JVM processes on the local machine
  -h  this help

jcmdjcmd -ljps -lm这三个命令输出信息差不多,随便挑一个用一个。

jcmd 可以使用的命令:

❯ jcmd 8560 help
8560:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.

例如:

❯ jcmd 8560 VM.flags
8560:
-XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:CICompilerCount=12 -XX:ConcGCThreads=3 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=503316480 -XX:+ManagementServer -XX:MarkStackSize=4194304 -XX:MaxGCPauseMillis=50 -XX:MaxHeapSize=8032092160 -XX:MaxNewSize=4819255296 -XX:MinHeapDeltaBytes=1048576 -XX:TieredStopAtLevel=1 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation

查看堆要使用绝对路径

❯ jcmd 8560 help GC.heap_dump
8560:
GC.heap_dump
Generate a HPROF format dump of the Java heap.

Impact: High: Depends on Java heap size and content. Request a full GC unless the '-all' option is specified.

Permission: java.lang.management.ManagementPermission(monitor)

Syntax : GC.heap_dump [options] <filename>

Arguments:
        filename :  Name of the dump file (STRING, no default value)

Options: (options must be specified using the <key> or <key>=<value> syntax)
        -all : [optional] Dump all objects, including unreachable objects (BOOLEAN, false)
# 两者效果差不多; jcmd 需要指定绝对路径; jmap 不能指定绝对路径
jcmd 8560 GC.heap_dump -all=true ~/8560-by-jcmd.hprof
jmap -dump:file=./8560-by-jmap.hprof 11155
jstack

jstack 工具可以打印出 Java 线程的调用栈信息(Stack Trace)。一般用来查看存在哪些线程,诊断是否存在死锁等。

这时候就看出来给线程(池)命名的必要性了(开发不规范,整个项目都是坑),具体可参考阿里巴巴的 Java 开发规范。

查看帮助信息

❯ jstack -h
Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

选项说明:

  • -F:强制执行 Thread Dump,可在 Java 进程卡死(hung 住)时使用,此选项可能需要系统权限。
  • -m:混合模式(mixed mode),将 Java 帧和 native 帧一起输出,此选项可能需要系统权限。
  • -l:长列表模式,将线程相关的 locks 信息一起输出,比如持有的锁,等待的锁。

常用用法:

jstack 8560

在 Linux 和 macOS 上,jstack pid 的效果跟 kill -3 pid 相同。

kill -3 PID

(1)如果项目通过Tomcat进行发布(普通的web项目),则对应的堆栈信息会打印在catalina.out文件中。

(2)如果项目是基于SpringBoot并且使用nohup java -jar xxx.jar & 命令运行,则java堆栈信息会在jar包所在的nohup.out文件中。

jrunscript 和 jjs

jrunscript 和 jjs 工具用来执行脚本,只要安装了 JDK 8+,就可以像 shell 命令一样执行相关的操作了。这两个工具背后,都是 JDK 8 自带的 JavaScript 引擎 Nashorn。

例子

❯ jjs
jjs> 1.1+2.2
3.3000000000000003
jjs> 
❯ jrunscript
nashorn> 1.1+2.2
3.3000000000000003
nashorn> 

jrunscript还可以执行脚本

jrunscript -l js -f /XXX/XXX/test.js

而 jjs 则只能交互模式,但是可以指定 JavaScript 支持的 ECMAScript 语言版本,比如 ES5 或者 ES6。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值