openjdk11
在谈论安全管理器时,我演示了利用Attach API进行的黑客攻击。 后者要求知道要附加的JVM的PID。 因为我的好朋友Evgeny Mandrikov无法参加在乌克兰Devoxx的演讲,所以我为他做了一个快速的私人演示。
要获取我想附加的JVM的PID,我使用了ps -ef | grep java
ps -ef | grep java
命令。 那时,Evgeny告诉了我有关jps
命令的信息,我知道除了最常见的JDK命令之外,还有很多我不知道的JDK命令。 以下是有关可用于解决已部署应用程序问题的列表。
jps:打印正在运行的JVM
要显示包含或多或少数据的正在运行的JVM的列表,请使用jps
命令行实用程序工具。
您可以使用
jps
命令列出目标系统上已jps
到的JVM。 此命令是实验性的,不受支持 。
jps是Java 6中引入的。它充分说明了“实验性”的真正含义。
jps
默认情况下,列表仅显示PID和启动的类的简单名称(或启动的JAR的名称):
560 Jps 99714 spring-petclinic-2.0.0.BUILD-SNAPSHOT.jar 95689 CommandServer
其他选项允许显示更多数据:
选项 | 描述 |
---|---|
| Displays the fully-qualified class name, or the JAR’s full path |
| Displays arguments used to launch the JVM e.g. |
| Displays parameters passed to the application e.g. the |
在系统状态下,以下输出将启用所有上述选项:
99714 target/spring-petclinic-2.0.0.BUILD-SNAPSHOT.jar 679 sun.tools.jps.Jps -lvm -Xms8m \ -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home 95689 org.asciidoctor.diagram.CommandServer -Djava.awt.headless=true
jinfo:在JVM上打印启动数据
生产问题要求获取有关特定正在运行的JVM的其他信息。 该数据包括整套JVM标志,JVM参数和系统属性。
您可以使用jinfo命令为指定的Java进程生成Java配置信息。 此命令是实验性的,不受支持。
jinfo 95689
这是一个示例结果(为了更好的可读性,对其进行了删节和格式化):
Java System Properties: #Fri Dec 07 16:22:25 CET 2018 gopherProxySet=false awt.toolkit=sun.lwawt.macosx.LWCToolkit java.specification.version=11 sun.cpu.isalist= sun.jnu.encoding=UTF-8 ... java.class.version=55.0 socksNonProxyHosts=local|*.local|169.254/16|*.169.254/16 VM Flags: -XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1ConcRefinementThreads=4 -XX:G1HeapRegionSize=1048576 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=268435456 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=4294967296 -XX:MaxNewSize=2576351232 -XX:MinHeapDeltaBytes=1048576 -XX:NonNMethodCodeHeapSize=5830092 -XX:NonProfiledCodeHeapSize=122914074 -XX:ProfiledCodeHeapSize=122914074 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC VM Arguments: jvm_args: -Djava.awt.headless=true java_command: org.asciidoctor.diagram.CommandServer java_class_path (initial): ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/server-1.3.13.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/ditaa-1.3.13.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/ditaamini-0.11.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/plantuml-1.3.13.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/plantuml.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/jlatexmath-minimal-1.0.5.jar: ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/batik-all-1.7.jar Launcher Type: SUN_STANDARD
选项允许限制显示的内容:
选项 | 描述 |
---|---|
| Displays only flag-related information |
| Displays only system properties |
jmap:在JVM上打印与类相关的数据
接下来,有必要深入了解JVM上与类相关的数据:类加载器统计信息,等待完成的对象和对象堆。
您可以使用jmap命令来打印指定进程的详细信息。 此命令是实验性的,不受支持。
根据使用的选项,输出是不同的。
-
打印类加载器统计信息
-
jmap-clstats 95689
Index Super InstBytes KlassBytes annotations CpAll MethodCount Bytecodes MethodAll ROAll RWAll Total ClassName 1 -1 1686600 504 0 0 0 0 0 24 616 640 [B 2 -1 485288 504 0 0 0 0 0 24 616 640 [I 3 20 420984 616 128 14224 109 4577 64472 18640 62104 80744 java.lang.String 4 -1 375216 504 0 0 0 0 0 24 616 640 [C 5 20 374448 672 0 22120 139 5682 46936 24616 47008 71624 java.lang.Class 6 -1 238888 504 0 0 0 0 0 24 616 640 [Ljava.lang.Object; 7 20 165440 584 0 1392 7 149 1864 1152 3008 4160 java.util.HashMap$Node 8 20 141856 592 0 1368 9 213 2776 1488 3584 5072 java.util.concurrent.ConcurrentHashMap$Node 9 20 71120 584 0 1400 7 171 2264 1208 3384 4592 java.util.TreeMap$Entry ... 3085 3084 0 632 0 808 5 71 960 640 1920 2560 sun.util.resources.TimeZoneNamesBundle 3086 20 0 600 0 1256 5 159 1000 856 2264 3120 sun.util.resources.provider.NonBaseLocaleDataMetaInfo 5147912 1947360 10656 6473512 31831 1647775 9869272 6170712 13100408 19271120 Total 26.7% 10.1% 0.1% 33.6% - 8.6% 51.2% 32.0% 68.0% 100.0% Index Super InstBytes KlassBytes annotations CpAll MethodCount Bytecodes MethodAll ROAll RWAll Total ClassName
打印Java对象堆的直方图
-
jmap-histo 95689
num #instances #bytes class name (module) ------------------------------------------------------- 1: 2578716 182530328 [I ( [email protected] ) 2: 261988 71251184 [Z ( [email protected] ) 3: 798811 57514392 java.util.regex.Matcher ( [email protected] ) 4: 413769 28433240 [B ( [email protected] ) 5: 296086 26055568 java.util.regex.Pattern ( [email protected] ) 6: 301073 16858024 [Ljava.lang.Object; ( [email protected] ) 7: 276719 15496264 [Ljava.util.regex.Pattern$GroupHead; ( [email protected] ) 8: 798811 13032760 [Ljava.util.regex.IntHashSet; ( [email protected] ) 9: 318781 7650744 java.util.regex.Pattern$BmpCharProperty ( [email protected] ) 10: 289648 6951552 java.util.ArrayList ( [email protected] ) ... 1616: 1 16 sun.util.logging.PlatformLogger ( [email protected] ) 1617: 1 16 sun.util.resources.LocaleData$LocaleDataStrategy ( [email protected] ) 1618: 1 16 sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo ( [email protected] ) Total 10605127 526098920
jstack:JVM的打印线程
然后,如果问题与线程有关( 例如死锁或活动锁),则有关正在运行的线程的详细数据将派上用场。
您可以使用jstack命令为指定的Java进程打印Java线程的Java堆栈跟踪。 此命令是实验性的,不受支持。
jstack 95689
2018-12-07 19:06:01 Full thread dump OpenJDK 64-Bit Server VM (11.0.1+13 mixed mode): Threads class SMR info: _java_thread_list=0x00007fd1212fb270, length=13, elements={ 0x00007fd120015800, 0x00007fd120051000, 0x00007fd120053800, 0x00007fd11e89c000, 0x00007fd120045800, 0x00007fd11f00f800, 0x00007fd12004a800, 0x00007fd11e8d9800, 0x00007fd120065000, 0x00007fd11f883000, 0x00007fd11f075800, 0x00007fd11ed4b000, 0x00007fd11f30e800 } "main" #1 prio=5 os_prio=31 cpu=314567.92ms elapsed=2035.03s tid=0x00007fd120015800 nid=0x2403 runnable [0x000070000bbac000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0( [email protected] /Native Method) at java.net.SocketInputStream.socketRead( [email protected] /SocketInputStream.java:115) at java.net.SocketInputStream.read( [email protected] /SocketInputStream.java:168) at java.net.SocketInputStream.read( [email protected] /SocketInputStream.java:140) at java.io.BufferedInputStream.fill( [email protected] /BufferedInputStream.java:252) at java.io.BufferedInputStream.read( [email protected] /BufferedInputStream.java:271) - locked <0x00000007000d0558> (a java.io.BufferedInputStream) at org.asciidoctor.diagram.HTTPInputStream.readLine(HTTPInputStream.java:20) at org.asciidoctor.diagram.HTTPInputStream.readRequest(HTTPInputStream.java:56) at org.asciidoctor.diagram.CommandServer.processRequests(CommandServer.java:61) at org.asciidoctor.diagram.CommandServer.main(CommandServer.java:25) ... "process reaper" #109 daemon prio=10 os_prio=31 cpu=538.50ms elapsed=1683.17s tid=0x00007fd11f30e800 nid=0x6507 waiting on condition [0x000070000ba4e000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park( [email protected] /Native Method) - parking to wait for <0x000000070016fe20> (a java.util.concurrent.SynchronousQueue$TransferStack) at java.util.concurrent.locks.LockSupport.parkNanos( [email protected] /LockSupport.java:234) at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill( [email protected] /SynchronousQueue.java:462) at java.util.concurrent.SynchronousQueue$TransferStack.transfer( [email protected] /SynchronousQueue.java:361) at java.util.concurrent.SynchronousQueue.poll( [email protected] /SynchronousQueue.java:937) at java.util.concurrent.ThreadPoolExecutor.getTask( [email protected] /ThreadPoolExecutor.java:1053) at java.util.concurrent.ThreadPoolExecutor.runWorker( [email protected] /ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run( [email protected] /ThreadPoolExecutor.java:628) at java.lang.Thread.run( [email protected] /Thread.java:834) "VM Thread" os_prio=31 cpu=1139.30ms elapsed=2035.01s tid=0x00007fd11f88e000 nid=0x4b03 runnable "GC Thread#0" os_prio=31 cpu=1888.39ms elapsed=2035.03s tid=0x00007fd11e805000 nid=0x5203 runnable "GC Thread#1" os_prio=31 cpu=1951.89ms elapsed=2034.53s tid=0x00007fd11e8e1800 nid=0x9903 runnable "GC Thread#2" os_prio=31 cpu=1897.20ms elapsed=2034.53s tid=0x00007fd11e8e2800 nid=0x5f03 runnable "GC Thread#3" os_prio=31 cpu=1901.78ms elapsed=2034.53s tid=0x00007fd11e90d000 nid=0x6103 runnable "G1 Main Marker" os_prio=31 cpu=0.57ms elapsed=2035.03s tid=0x00007fd11e84a000 nid=0x5003 runnable "G1 Conc#0" os_prio=31 cpu=36.31ms elapsed=2035.03s tid=0x00007fd11e84a800 nid=0x3003 runnable "G1 Refine#0" os_prio=31 cpu=8.48ms elapsed=2035.03s tid=0x00007fd11f882000 nid=0x3203 runnable "G1 Refine#1" os_prio=31 cpu=2.95ms elapsed=2034.52s tid=0x00007fd11e9b1000 nid=0x9703 runnable "G1 Refine#2" os_prio=31 cpu=0.06ms elapsed=2034.36s tid=0x00007fd11f939800 nid=0x6303 runnable "G1 Young RemSet Sampling" os_prio=31 cpu=898.32ms elapsed=2035.03s tid=0x00007fd11e858800 nid=0x3303 runnable "VM Periodic Task Thread" os_prio=31 cpu=933.68ms elapsed=2034.94s tid=0x00007fd11f00c800 nid=0xa603 waiting on condition JNI global refs: 98, weak refs: 5
要检查锁,请使用-l
选项。 打印以下内容:
... "main" #1 prio=5 os_prio=31 cpu=489307.36ms elapsed=3019.58s tid=0x00007fd120015800 nid=0x2403 runnable [0x000070000bbac000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0( [email protected] /Native Method) at java.net.SocketInputStream.socketRead( [email protected] /SocketInputStream.java:115) at java.net.SocketInputStream.read( [email protected] /SocketInputStream.java:168) at java.net.SocketInputStream.read( [email protected] /SocketInputStream.java:140) at java.io.BufferedInputStream.fill( [email protected] /BufferedInputStream.java:252) at java.io.BufferedInputStream.read( [email protected] /BufferedInputStream.java:271) - locked <0x00000007000d0558> (a java.io.BufferedInputStream) at org.asciidoctor.diagram.HTTPInputStream.readLine(HTTPInputStream.java:20) at org.asciidoctor.diagram.HTTPInputStream.readRequest(HTTPInputStream.java:56) at org.asciidoctor.diagram.CommandServer.processRequests(CommandServer.java:61) at org.asciidoctor.diagram.CommandServer.main(CommandServer.java:25) Locked ownable synchronizers: (1) - None "Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.94ms elapsed=3019.55s tid=0x00007fd120051000 nid=0x3603 waiting on condition [0x000070000c2c1000] java.lang.Thread.State: RUNNABLE at java.lang.ref.Reference.waitForReferencePendingList( [email protected] /Native Method) at java.lang.ref.Reference.processPendingReferences( [email protected] /Reference.java:241) at java.lang.ref.Reference$ReferenceHandler.run( [email protected] /Reference.java:213) Locked ownable synchronizers: (1) - None ...
- 看,没有锁!
jconsole:监视JVM
具有正在运行的JVM内部的图形视图可以节省生命。
您可以使用
jconsole
命令启动图形控制台来监视和管理Java应用程序。
恕我直言,JConsole是Java开发人员工具栏中最重要的工具之一。
它在关键区域提供了正在运行的JVM的图形视图:
-
记忆
-
该控制台能够显示与内存相关的不同图形:堆,非堆,旧生成,伊甸园,幸存者等。
线程数
-
JConsole可以显示选定时间范围内线程数的演变。 它还可以分别显示每个线程,以及其名称,状态和堆栈。
班级
-
它还可以显示已加载的类数。
虚拟机摘要
-
该工具可以显示与JVM相关的数据:
- VM参数
- 类路径
- 库路径
- 引导类路径
- 堆大小
- 等等
豆类
-
JConsole能够以树状结构显示所有可用的MBean,包括属性和方法。 此外,它允许设置其属性,并调用其方法。
JConsole基于插件体系结构 。
结论
JDK提供了许多现成的工具来帮助开发人员。 无论您是否使用IDE,它们都是开发人员日常工作中的一项巨大资产。
openjdk11