jdk bin目录下自带的工具介绍

Java JDK 自带的工具

Java JDK 的bin目录中有许多很有用的自带的工具。这些工具可以很好地帮助我们编译、运行、监控、分析Java程序。

工具名称 描述
appletviewer.exe 用于运行并浏览applet小程序。
apt.exe 注解处理工具(Annotation Processing Tool),主要用于注解处理。
extcheck.exe 扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突。
idlj.exe IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定。IDL意即接口定义语言(Interface Definition Language)。
jabswitch.exe Java访问桥开关(Java Access Bridge switch),用于启用/禁用Java访问桥。Java访问桥内置于Java 7 Update 6及以上版本,主要为Windows系统平台提供一套访问Java应用的API。
jar.exe jar文件管理工具,主要用于打包压缩、解压jar文件。
jarsigner.exe jar密匙签名工具。
java.exe Java运行工具,用于运行.class字节码文件或.jar文件。
javac.exe Java编译工具(Java Compiler),用于编译Java源代码文件。
javadoc.exe Java文档工具,主要用于根据Java源代码中的注释信息生成HTML格式的API帮助文档。
javafxpackager.exe JavaFX包装器,用于执行与封装或签名JavaFX应用有关的任务。
javah.exe Java头文件工具,用于根据Java类生成C/C++头文件和源文件(主要用于JNI开发领域)。
javap.exe Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件。
java-rmi.exe Java远程方法调用(Java Remote Method Invocation)工具,主要用于在客户机上调用远程服务器上的对象。
javaw.exe Java运行工具,用于运行.class字节码文件或.jar文件,但不会显示控制台输出信息,适用于运行图形化程序。
javaws.exe Java Web Start,使您可以从Web下载和运行Java应用程序,下载、安装、运行、更新Java应用程序都非常简单方便。
jcmd.exe Java 命令行(Java Command),用于向正在运行的JVM发送诊断命令请求。
jconsole.exe 图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息。
jdb.exe Java调试工具(Java Debugger),主要用于对Java应用进行断点调试。
jhat.exe Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。
jinfo.exe Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。
jmap.exe Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
jmc.exe Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。
jps.exe JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上的HotSpot JVM的Java进程信息。
jrunscript.exe Java命令行脚本外壳工具(command line script shell),主要用于解释执行javascript、groovy、ruby等脚本语言。
jsadebugd.exe Java可用性代理调试守护进程(Java Serviceability Agent Debug Daemon),主要用于附加到指定的Java进程、核心文件,或充当一个调试服务器。
jstack.exe Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
jstat.exe JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息。
jstatd.exe jstatd(VM jstatd Daemon)工具是一个RMI服务器应用,用于监测HotSpot JVM的创建和终止,并提供一个接口,允许远程监测工具附加到运行于本地主机的JVM上。
jvisualvm.exe JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息。
keytool.exe 密钥和证书管理工具,主要用于密钥和证书的创建、修改、删除等。
kinit.exe 主要用于获取或缓存Kerberos协议的票据授权票据。
klist.exe 允许用户查看本地凭据缓存和密钥表中的条目(用于Kerberos协议)。
ktab.exe Kerberos密钥表管理工具,允许用户管理存储于本地密钥表中的主要名称和服务密钥。
native2ascii.exe 本地编码到ASCII编码的转换器(Native-to-ASCII Converter),用于"任意受支持的字符编码"和与之对应的"ASCII编码和(或)Unicode转义"之间的相互转换。
orbd.exe 对象请求代理守护进程(Object Request Broker Daemon),它使客户端能够透明地定位和调用位于CORBA环境的服务器上的持久对象。
pack200.exe JAR文件打包压缩工具,它可以利用Java类特有的结构,对普通JAR文件进行高效压缩,以便于能够更快地进行网络传输。
packager.exe 这是微软提供的对象包装程序,用于对象安装包。
policytool.exe 策略工具,用于管理用户策略文件(.java.policy)。
rmic.exe Java RMI 编译器,为使用JRMP或IIOP协议的远程对象生成stub、skeleton、和tie类,也用于生成OMG IDL。
rmid.exe Java RMI 激活系统守护进程,rmid启动激活系统守护进程,允许在虚拟机中注册或激活对象。
rmiregistry.exe Java 远程对象注册表,用于在当前主机的指定端口上创建并启动一个远程对象注册表。
schemagen.exe XML schema生成器,用于生成XML schema文件。
serialver.exe 序列版本命令,用于生成并返回serialVersionUID。
servertool.exe Java IDL 服务器工具,用于注册、取消注册、启动和终止持久化的服务器。
tnameserv.exe Java IDL瞬时命名服务。
unpack200.exe JAR文件解压工具,将一个由pack200打包的文件解压提取为JAR文件。
wsgen.exe XML Web Service 2.0的Java API,生成用于JAX-WS Web Service的JAX-WS便携式产物。
wsimport.exe XML Web Service 2.0的Java API,主要用于根据服务端发布的wsdl文件生成客户端存根及框架
xjc.exe 主要用于根据XML schema文件生成对应的Java类。

参考文章:https://blog.csdn.net/u014042066/article/details/78831435

下面只会介绍一下一些的工具:

1、 jps
2、 jinfo
3、 jmap
4、 jstack
5、 jconsole
6、 jstat
7、 visualVM
8、 javadoc
9、 javah
10、 javap
11、 jhat
12、 jmc

1、jps 列出Java进程

E:\workspace\demo>jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]


– 列出 java 进程,类似于 ps 命令

– 参数 -q 可以指定 jps 只输出进程 ID , 不输出类的短 名称

– 参数 -m 可以用于输出传递给 Java 进程(主函数)的 参数

– 参数 -l 可以用于输出主函数的完整 路径

– 参数 -v 可以显示传递给 JVM 的参数

例如:
E:\workspace\demo>jps -l
6496 sun.tools.jps.Jps
14164 org.jetbrains.jps.cmdline.Launcher
3796 com.guodi.model.ModelApplication
2140 org.jetbrains.jps.cmdline.Launcher

有时候使用jps命令可能会没有任何输出

这个主要是因为jps命令需要在/tmp目录下的”hsperfdata_用户名“ 目录中存放进程ID,如果我们使用普通用户登录,就可能没有权限去创建这个文件夹。(windows可以通过命令行执行"%tmp%"来查看tmp目录的全路径)

解决方法:

方法一:直接使用管理员登录

方法二:在/tmp目录中创建一个”hsperfdata_用户名“ 文件夹,并设置权限。

2、jinfo 查看/修改JVM参数

E:\workspace\demo>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

这个命令主要是查看/修改JVM的一下属性、参数、标志的,需要先知道Java进程的PID,可以搭配jps命令一起使用。

例子:
E:\workspace\demo>jinfo 3796
Attaching to process ID 3796, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11
Java System Properties:

spring.output.ansi.enabled = always
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.231-b11
sun.boot.library.path = D:\software\Java\jre\bin
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = ;
java.rmi.server.randomIDs = true
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level =
sun.java.launcher = SUN_STANDARD
user.script =
user.country = CN
user.dir = E:\workspace\nj-onemap
java.vm.specification.name = Java Virtual Machine Specification
PID = 3796
java.runtime.version = 1.8.0_231-b11
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = D:\software\Java\jre\lib\endorsed
line.separator =

java.io.tmpdir = C:\Users\PC\AppData\Local\Temp\
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
http.maxRedirects = 5
sun.jnu.encoding = GBK
java.library.path = D:\software\Java\bin;
spring.beaninfo.ignore = true
sun.nio.ch.bugLevel =
java.class.version = 52.0
java.specification.name = Java Platform API Specification
spring.jmx.enabled = true
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
spring.liveBeansView.mbeanDomain =
os.version = 10.0
user.home = C:\Users\PC
user.timezone = Asia/Shanghai
nacos.logging.path = C:\Users\PC/logs/nacos
catalina.useNaming = false
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = UTF-8
@appId = model
java.specification.version = 1.8
catalina.home = C:\Users\PC\AppData\Local\Temp\tomcat.8757673584996351040.9099
user.name = PC

VM Flags:
Non-default VM flags: -XX:-BytecodeVerificationLocal -XX:+UseParallelGC
Command line:  -XX:TieredStopAtLevel=1  -Dfile.encoding=UTF-8

程序中我们经常会使用System.getProperty("os.name")来获取系统属性,但常常我们不知道有哪些属性可以获取,那这时就可以通过jinfo来看有哪些系统属性了。

3、jmap查看JVM内存情况

jmap命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。

打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。

E:\workspace\demo>jmap
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

  • pid: 目标进程的PID,进程编号,可以采用ps -ef | grep java 查看java进程的PID;
  • executable: 产生core dump的java可执行程序;
  • core: 将被打印信息的core dump文件;
  • remote-hostname-or-IP: 远程debug服务的主机名或ip; > server-id: 唯一id,假如一台主机上多个远程debug服务;

如果什么参数都不填的话,输出的内容用途不是很大

E:\workspace\demo>jmap 7876
Attaching to process ID 7876, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11
0x000000006e290000      8856K   D:\software\Java\jre\bin\server\jvm.dll
0x000000006f750000      840K    D:\software\Java\jre\bin\msvcr100.dll
0x00007ff6c7000000      220K    D:\software\Java\bin\java.exe
0x00007ffb04a80000      1640K   D:\software\Java\jre\bin\awt.dll
0x00007ffb0ca20000      164K    D:\software\Java\jre\bin\java.dll
0x00007ffb0f0e0000      72K     C:\Windows\System32\winrnr.dll
0x00007ffb0f100000      84K     C:\Windows\system32\wshbth.dll
0x00007ffb0f120000      108K    C:\Windows\system32\pnrpnsp.dll
0x00007ffb10380000      92K     C:\Windows\system32\napinsp.dll

参数 -dump

-dump:[live,]format=b,file= 使用hprof二进制形式,输出jvm的heap内容到文件中. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件。生成的文件需要使用其他工具进行查看。

E:\workspace\demo>jmap -dump:live,format=b,file=myjmapfile.txt 7876
Dumping heap to E:\workspace\demo\myjmapfile.txt ...
Heap dump file created

注意,此时你会得到一个非常大的文件,内容是二进制的,不要直接记事本打开。

参数 -finalizerinfo

打印正等候回收的对象的信息,指那些执行了finalize方法的对象。

E:\workspace\demo>jmap -finalizerinfo 7876
Attaching to process ID 7876, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11
Number of objects pending for finalization: 0 (等候回收的对象为0个)

参数 -heap

打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况。

E:\workspace\demo>jmap -heap 7876
Attaching to process ID 7876, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:   ##堆配置情况,也就是JVM参数配置的结果[平常说的tomcat配置JVM参数,就是在配置这些]
  MinHeapFreeRatio         = 0   ##最小堆使用比例
  MaxHeapFreeRatio         = 100 ##最大堆可用比例
  MaxHeapSize              = 4282384384 (4084.0MB) ##最大堆空间大小
  NewSize                  = 89128960 (85.0MB)     ##新生代分配大小
  MaxNewSize               = 1427111936 (1361.0MB) ##最大可新生代分配大小
  OldSize                  = 179306496 (171.0MB)   ##老年代大小
  NewRatio                 = 2                     ##新生代比例
  SurvivorRatio            = 8                     ##Eden占新生代的比例
  MetaspaceSize            = 21807104 (20.796875MB)##元空间大小
  CompressedClassSpaceSize = 1073741824 (1024.0MB) 
  MaxMetaspaceSize         = 17592186044415 MB     ##最大元空间大小
  G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:           ##堆使用情况【堆内存实际的使用情况】
PS Young Generation
Eden Space:           ##新生代(伊甸区Eden区 + 幸存区survior(From+To)空间)
  capacity = 391118848 (373.0MB)             ##伊甸区容量
  used     = 52733904 (50.29096984863281MB)  ##已经使用大小
  free     = 338384944 (322.7090301513672MB) ##剩余容量
  13.482833739579842% used                   ##使用比例
From Space:
  capacity = 6815744 (6.5MB)                 ##survior1区容量
  used     = 0 (0.0MB)                       ##surviror1区已使用情况
  free     = 6815744 (6.5MB)                 ##surviror1区剩余容量
  0.0% used                                  ##survior1区使用比例
To Space:
  capacity = 17825792 (17.0MB)               ##survior2区容量
  used     = 0 (0.0MB)                       ##survior2区已使用情况
  free     = 17825792 (17.0MB)               ##survior2区剩余容量
  0.0% used                                  ##survior2区使用比例
PS Old Generation                 ##老年代使用情况       
  capacity = 281018368 (268.0MB)             ##老年代容量
  used     = 73405008 (70.00447082519531MB)  ##老年代已使用容量
  free     = 207613360 (197.9955291748047MB) ##老年代剩余容量
  26.121071203431086% used                   ##老年代使用比例

35617 interned Strings occupying 3962912 bytes. ##内部字符串占了多少内存

参数 -histo[:live]

打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量。

序号     (实例数量)        总字节大小 类名
num     #instances       #bytes  class name
----------------------------------------------
  1:        167535       17455384  [C
  2:         87893        7734584  java.lang.reflect.Method
  3:        165660        3975840  java.lang.String
  4:         98711        3948440  java.util.LinkedHashMap$Entry
  5:        121148        3876736  java.util.concurrent.ConcurrentHashMap$Node
  6:         68818        3303264  org.aspectj.weaver.reflect.ShadowMatchImpl
  7:         38303        2428472  [Ljava.lang.Object;
  8:         68818        2202176  org.aspectj.weaver.patterns.ExposedState
  9:         27088        2177584  [Ljava.util.HashMap$Node;
 10:         13590        1540736  java.lang.Class
 11:         26632        1491392  java.util.LinkedHashMap
 12:           385        1108256  [Ljava.util.concurrent.ConcurrentHashMap$Node;

使用jmap -histo pid>a.log日志将其保存,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。

参数 -clstats

打印classload和jvm heap永久代的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.

E:\workspace\demo>jmap -clstats 19916
Attaching to process ID 19916, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness........................................liveness analysis may be inaccurate ...
(类加载器)       (装载的类数量)     (父类加载器)      (是否存活) (类型)
class_loader    classes bytes   parent_loader   alive?  type

<bootstrap>     2950    5119801   null          live    <internal>
0x00000006c1c84bc8      1       1472    0x00000006c0c05c20      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
0x00000006c1c89bc8      1       1471      null          dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
0x00000006c3898588      1       880     0x00000006c0c05c20      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
0x00000006c0c05c80      30      34638     null          live    sun/misc/Launcher$ExtClassLoader@0x00000007c000fd00

total = 364     11985   20597658            N/A         alive=9, dead=355           N/A

4、jstack查看Java运行堆栈

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。

Windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid。

如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

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

基本上这个命令只有 -l 这一个参数是有用的。

一般情况下,通过jstack输出的线程信息主要包括:jvm自身线程、用户线程等。其中jvm线程会在jvm启动时就会存在。对于用户线程则是在用户访问时才会生成。

一般情况下,会有JVM内部的后台线程和用户级别的线程。

2020-12-10 17:53:56
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode):

"Keep-Alive-Timer" #515 daemon prio=8 os_prio=1 tid=0x0000000026961000 nid=0x31a8 waiting on condition [0x000000000154f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:172)
	at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
	- None

"com.alibaba.nacos.naming.beat.sender" #108 daemon prio=5 os_prio=0 tid=0x0000000026960800 nid=0x27b0 waiting on condition [0x00000000246ee000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000006c426bef0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
	- None

"DestroyJavaVM" #101 prio=5 os_prio=0 tid=0x0000000026948000 nid=0x3024 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Druid-ConnectionPool-Destroy-435070844" #38 daemon prio=5 os_prio=0 tid=0x0000000023873000 nid=0x469c waiting on condition [0x00000000256ef000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:2522)

   Locked ownable synchronizers:
	- None

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x0000000020089000 nid=0x2168 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001ffbb800 nid=0x4c28 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001ff9d000 nid=0x93c runnable [0x000000002104f000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	- locked <0x00000006c0c31f48> (a java.io.InputStreamReader)
	at java.io.InputStreamReader.read(InputStreamReader.java:184)
	at java.io.BufferedReader.fill(BufferedReader.java:161)
	at java.io.BufferedReader.readLine(BufferedReader.java:324)
	- locked <0x00000006c0c31f48> (a java.io.InputStreamReader)
	at java.io.BufferedReader.readLine(BufferedReader.java:389)
	at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:61)

   Locked ownable synchronizers:
	- None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001ef66000 nid=0x2ffc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001efc4800 nid=0x40e4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001d14c000 nid=0x17e0 in Object.wait() [0x000000001f51f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
	- locked <0x00000006c0c3a688> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

   Locked ownable synchronizers:
	- None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001ef40800 nid=0x10ac in Object.wait() [0x000000001f41f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x00000006c0c1c388> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
	- None

"VM Thread" os_prio=2 tid=0x000000001d13d000 nid=0x2630 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000003417000 nid=0x2b6c runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000003419000 nid=0x48c4 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000341a800 nid=0x3200 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000341c000 nid=0x29cc runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x000000000341e800 nid=0x2c68 runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x000000000341f800 nid=0x1dfc runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000003422800 nid=0x5b4 runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000003425000 nid=0x3600 runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x00000000202d5000 nid=0x1d4 waiting on condition 

JNI global references: 1274


从上述的代码示例中我们可以看到该用户线程的以下几类信息:

  • 线程的状态
  • 线程的调用情况
  • 线程对资源的锁定情况

线程的状态有以下几种:

  • Runnable

    该状态表示线程具备所有运行条件,在运行队列中准备操作系统的调度,或者正在运行。

  • Waiton condition

    ​ 该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合stacktrace来分析。最常见的情况是线程在等待网络的读写,比如当网络数据没有准备好读时,线程处于这种等待状态,而一旦有数据准备好读之后,线程会重新激活,读取并处理数据。在 Java引入 NIO之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在 NIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。

    ​ 如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用 dtrace工具看系统调用的情况,如果观察到 read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。

    ​ 另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。

  • Waitingfor monitor entry 和 in Object.wait()

    “Waiting for monitorentry”说明代码被synchronized包含着,线程需要等待获取锁。

    “in Object.wait()”说明代码自己执行了wait方法,现在等待中

5、jconsole可视化监视和管理控制台

这是一个windows系统上的工具,可以对java程序进行监控管理的一个可视化应用。

关于MBean,以后再写文章说明,现在只要知道他有点类似于spring的IOC容器里面的bean就行了,因为这玩意跟JMX和RMI都有点关系。

远端连接URL样例:service:jmx:rmi://127.0.0.1:8888/jndi/rmi://127.0.0.1:8888/hongcheng

第一个127.0.0.1:8888是JMX地址,可以不填,如果填就和后面的一样

第二个127.0.0.1:8888是RMI的地址,必填,一般是本机的地址

/hongcheng,一个URL path,类似context path,默认是/jmxrmi,可以为空。

6、jstat静态监控工具

Jstat是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。

jstat -<option> PID [间隔时间/毫秒] [查询次数]

E:\workspace\demo>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.

E:\workspace\demo>jstat -options
-class          (类加载统计)
-compiler       (编译统计)
-gc             (垃圾回收统计)
-gccapacity     (堆内存统计)
-gccause        (最近一次GC统计和原因)
-gcmetacapacity (JDK8 下 元数据空间统计)
-gcnew          (新生代垃圾回收统计)
-gcnewcapacity  (新生代内存统计)
-gcold          (老年代垃圾回收统计)
-gcoldcapacity  (老年代内存统计)
-gcutil         (总结垃圾回收统计)
-printcompilation(JVM编译方法统计)

参数说明:

-class (类加载统计)

E:\workspace\demo>jstat -class 15712
Loaded  Bytes  Unloaded  Bytes     Time
 13135 25262.8        0     0.0       8.26
显示列名 具体描述
Loaded 装载的类的数量
Bytes 装载类所占用的字节数
Unloaded 卸载类的数量
Bytes 卸载类的字节数
Time 装载和卸载类所花费的时间

-compiler (显示VM编译的数量等信息)

E:\workspace\demo>jstat -compiler 15712
Compiled Failed Invalid   Time   FailedType FailedMethod
   10456      0       0     2.28          0
显示列名 具体描述
Compiled 编译任务执行数量
Failed 编译任务执行失败数量
Invalid 编译任务执行失效数量
Time 编译任务消耗时间
FailedType 最后一个编译失败任务的类型
FailedMethod 最后一个编译失败任务所在的类及方法

-gc (可以显示gc的信息,查看gc的次数,及时间)

E:\workspace\demo>jstat -gc 15712
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
2560.0 25088.0 2496.0  0.0   678400.0 157518.6  229888.0   71083.2   74112.0 70763.7 9600.0 9019.7     24    0.180   4      0.438    0.618
显示列名 具体描述
S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
S0U 年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U 年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC 年轻代中Eden(伊甸园)的容量 (字节)
EU 年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC Old代的容量 (字节)
OU Old代目前已使用空间 (字节)
MC 元空间的容量 (字节)
MU 元空间目前已使用空间 (字节)
CCSC 压缩类空间大小
CCSU 压缩类空间使用大小
YGC 年轻代垃圾回收次数
YGCT 年轻代垃圾回收消耗时间
FGC 老年代垃圾回收次数
FGCT 老年代垃圾回收消耗时间
GCT 垃圾回收消耗总时间

-gccapacity (堆内存统计)

E:\workspace\demo>jstat -gccapacity 15712
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
 87040.0 1393664.0 783872.0 2560.0 25088.0 678400.0   175104.0  2788352.0   229888.0   229888.0      0.0 1114112.0  74112.0      0.0 1048576.0   9600.0     24     4
显示列名 具体描述
NGCMN 新生代最小容量
NGCMX 新生代最大容量
NGC 当前新生代容量
S0C 第一个幸存区大小
S1C 第二个幸存区的大小
EC 伊甸园区的大小
OGCMN 老年代最小容量
OGCMX 老年代最大容量
OGC 当前老年代大小
OC 当前老年代大小
MCMN 最小元数据容量
MCMX 最大元数据容量
MC 当前元数据空间大小
CCSMN 最小压缩类空间大小
CCSMX 最大压缩类空间大小
CCSC 当前压缩类空间大小
YGC 年轻代gc次数
FGC 老年代GC次数

-gcmetacapacity (JDK8 下 元数据空间统计)

E:\workspace\demo>jstat -gcmetacapacity 15712
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT
   0.0  1114112.0    74112.0        0.0  1048576.0     9600.0    24     4    0.438    0.618

MCMN:最小元数据容量

MCMX:最大元数据容量

MC:当前元数据空间大小

CCSMN:最小压缩类空间大小

CCSMX:最大压缩类空间大小

CCSC:当前压缩类空间大小

YGC:年轻代垃圾回收次数

FGC:老年代垃圾回收次数

FGCT:老年代垃圾回收消耗时间

GCT:垃圾回收消耗总时间

-gcnew (新生代垃圾回收统计)

E:\workspace\demo>jstat -gcnew 15712
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
24576.0 2560.0    0.0 2464.0  7  15 24576.0 650752.0  10116.4     25    0.192

S0C:第一个幸存区大小

S1C:第二个幸存区的大小

S0U:第一个幸存区的使用大小

S1U:第二个幸存区的使用大小

TT: 对象在新生代存活的次数

MTT: 对象在新生代存活的最大次数

DSS: 期望的幸存区大小

EC:伊甸园区的大小

EU:伊甸园区的使用大小

YGC:年轻代垃圾回收次数

YGCT:年轻代垃圾回收消耗时间

-gcnewcapacity (新生代内存统计)

E:\workspace\demo>jstat -gcnewcapacity 15712
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
   87040.0  1393664.0   781824.0 464384.0  24576.0 464384.0   2560.0  1392640.0   650752.0    25     4

NGCMN:新生代最小容量

NGCMX:新生代最大容量

NGC:当前新生代容量

S0CMX:最大幸存1区大小

S0C:当前幸存1区大小

S1CMX:最大幸存2区大小

S1C:当前幸存2区大小

ECMX:最大伊甸园区大小

EC:当前伊甸园区大小

YGC:年轻代垃圾回收次数

FGC:老年代回收次数

-gcold(老年代垃圾回收统计)

E:\workspace\demo>jstat -gcold 15712
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
 74112.0  70763.7   9600.0   9019.7    229888.0     71091.2     25     4    0.438    0.630

MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-gcoldcapacity (老年代内存统计)

E:\workspace\demo>jstat -gcoldcapacity 15712
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
   175104.0   2788352.0    229888.0    229888.0    25     4    0.438    0.630

OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-gcutil(总结垃圾回收统计)

E:\workspace\demo>jstat -gcutil 15712
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00  96.25  14.72  30.92  95.48  93.96     25    0.192     4    0.438    0.630

S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

-printcompilation(JVM编译方法统计)

E:\workspace\demo>jstat -printcompilation  15712
Compiled  Size  Type Method
   10479      5    1 java/text/DecimalFormatSymbols getInfinity

Compiled:最近编译方法的数量

Size:最近编译方法的字节码数量

Type:最近编译方法的编译类型。

Method:方法名标识。

7、jvisualvm可视化的VM虚拟机分析工具

jvisualvm和jconsole类似,都是属于可视化工具,但是jvisualvm在功能上比jconsole更为强大。把它当成一个升级版的jconsole就行了。

8、javadoc Java文档工具

javadoc是一个根据Java源代码中的文档注释生成HTML格式的API文档的工具。

E:\workspace\demo\out\artifacts\demo_jar>javadoc -help
用法: javadoc [options] [packagenames] [sourcefiles] [@files]
  -overview <file>                 从 HTML 文件读取概览文档
  -public                          仅显示 public 类和成员
  -protected                       显示 protected/public 类和成员 (默认值)
  -package                         显示 package/protected/public 类和成员
  -private                         显示所有类和成员
  -help                            显示命令行选项并退出
  -doclet <class>                  通过替代 doclet 生成输出
  -docletpath <path>               指定查找 doclet 类文件的位置
  -sourcepath <pathlist>           指定查找源文件的位置
  -classpath <pathlist>            指定查找用户类文件的位置
  -cp <pathlist>                   指定查找用户类文件的位置
  -exclude <pkglist>               指定要排除的程序包列表
  -subpackages <subpkglist>        指定要递归加载的子程序包
  -breakiterator                   计算带有 BreakIterator 的第一个语句
  -bootclasspath <pathlist>        覆盖由引导类加载器所加载的
                                   类文件的位置
  -source <release>                提供与指定发行版的源兼容性
  -extdirs <dirlist>               覆盖所安装扩展的位置
  -verbose                         输出有关 Javadoc 正在执行的操作的信息
  -locale <name>                   要使用的区域设置, 例如 en_US 或 en_US_WIN
  -encoding <name>                 源文件编码名称
  -quiet                           不显示状态消息
  -J<flag>                         直接将 <flag> 传递到运行时系统
  -X                               输出非标准选项的提要

通过标准 doclet 提供:
  -d <directory>                   输出文件的目标目录
  -use                             创建类和程序包用法页面
  -version                         包含 @version 段
  -author                          包含 @author 段
  -docfilessubdirs                 递归复制文档文件子目录
  -splitindex                      将索引分为每个字母对应一个文件
  -windowtitle <text>              文档的浏览器窗口标题
  -doctitle <html-code>            包含概览页面的标题
  -header <html-code>              包含每个页面的页眉文本
  -footer <html-code>              包含每个页面的页脚文本
  -top    <html-code>              包含每个页面的顶部文本
  -bottom <html-code>              包含每个页面的底部文本
  -link <url>                      创建指向位于 <url> 的 javadoc 输出的链接
  -linkoffline <url> <url2>        利用位于 <url2> 的程序包列表链接至位于 <url> 的文档
  -excludedocfilessubdir <name1>:.. 排除具有给定名称的所有文档文件子目录。
  -group <name> <p1>:<p2>..        在概览页面中, 将指定的程序包分组
  -nocomment                       不生成说明和标记, 只生成声明。
  -nodeprecated                    不包含 @deprecated 信息
  -noqualifier <name1>:<name2>:... 输出中不包括指定限定符的列表。
  -nosince                         不包含 @since 信息
  -notimestamp                     不包含隐藏时间戳
  -nodeprecatedlist                不生成已过时的列表
  -notree                          不生成类分层结构
  -noindex                         不生成索引
  -nohelp                          不生成帮助链接
  -nonavbar                        不生成导航栏
  -serialwarn                      生成有关 @serial 标记的警告
  -tag <name>:<locations>:<header> 指定单个参数定制标记
  -taglet                          要注册的 Taglet 的全限定名称
  -tagletpath                      Taglet 的路径
  -charset <charset>               用于跨平台查看生成的文档的字符集。
  -helpfile <file>                 包含帮助链接所链接到的文件
  -linksource                      以 HTML 格式生成源文件
  -sourcetab <tab length>          指定源中每个制表符占据的空格数
  -keywords                        使程序包, 类和成员信息附带 HTML 元标记
  -stylesheetfile <path>           用于更改生成文档的样式的文件
  -docencoding <name>              指定输出的字符编码

9、javah 将Java类中native方法转出.h文件

根据Java类,将Java类中的native方法转成C语言的.h文件

E:\workspace\demo\out\artifacts\demo_jar>javah -help
用法:
  javah [options] <classes>
其中, [options] 包括:
  -o <file>                输出文件 (只能使用 -d 或 -o 之一)
  -d <dir>                 输出目录
  -v  -verbose             启用详细输出
  -h  --help  -?           输出此消息
  -version                 输出版本信息
  -jni                     生成 JNI 样式的标头文件 (默认值)
  -force                   始终写入输出文件
  -classpath <path>        从中加载类的路径
  -cp <path>               从中加载类的路径
  -bootclasspath <path>    从中加载引导类的路径
<classes> 是使用其全限定名称指定的
(例如, java.lang.Object)。

例如:

public class Test {
	private int a = 1;
/**
     * 主类
     * @param args 参数
     * @author 张三
     * */
    public static void main(String[] args) {
        System.out.println("hello world");
        for (String arg : args) {
            System.out.println(arg);
        }
    }
	
	native static String getStringFromJni();
}

执行javah后,将生成Test.h文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Test */

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test
 * Method:    getStringFromJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Test_getStringFromJni
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

10、javap反编译工具

E:\workspace\demo\out\artifacts\demo_jar>javap
用法: javap <options> <classes>
其中, 可能的选项包括:
  -help  --help  -?        输出此用法消息
  -version                 版本信息
  -v  -verbose             输出附加信息
  -l                       输出行号和本地变量表
  -public                  仅显示公共类和成员
  -protected               显示受保护的/公共类和成员
  -package                 显示程序包/受保护的/公共类
                           和成员 (默认)
  -p  -private             显示所有类和成员
  -c                       对代码进行反汇编
  -s                       输出内部类型签名
  -sysinfo                 显示正在处理的类的
                           系统信息 (路径, 大小, 日期, MD5 散列)
  -constants               显示最终常量
  -classpath <path>        指定查找用户类文件的位置
  -cp <path>               指定查找用户类文件的位置
  -bootclasspath <path>    覆盖引导类文件的位置

例子:

源码:
public class Test {
	private int a = 1;
	/**
     * 主类
     * @param args 参数
     * @author 张三
     * */
    public static void main(String[] args) {
        System.out.println("hello world");
        for (String arg : args) {
            System.out.println(arg);
        }
    }
	
	native static String getStringFromJni();
}

反编译后:
javap -v -l -private -c -s -sysinfo -constants -cp . Test
Classfile /D:/Desktop/1/c/Test.class
  Last modified 2020-12-15; size 601 bytes
  MD5 checksum 5380ccd3292ebe07341cd95d76b3cff3
  Compiled from "Test.java"
public class Test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#22         // java/lang/Object."<init>":()V
   #2 = Fieldref           #6.#23         // Test.a:I
   #3 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = String             #26            // hello world
   #5 = Methodref          #27.#28        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Class              #29            // Test
   #7 = Class              #30            // java/lang/Object
   #8 = Utf8               a
   #9 = Utf8               I
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               StackMapTable
  #17 = Class              #31            // "[Ljava/lang/String;"
  #18 = Utf8               getStringFromJni
  #19 = Utf8               ()Ljava/lang/String;
  #20 = Utf8               SourceFile
  #21 = Utf8               Test.java
  #22 = NameAndType        #10:#11        // "<init>":()V
  #23 = NameAndType        #8:#9          // a:I
  #24 = Class              #32            // java/lang/System
  #25 = NameAndType        #33:#34        // out:Ljava/io/PrintStream;
  #26 = Utf8               hello world
  #27 = Class              #35            // java/io/PrintStream
  #28 = NameAndType        #36:#37        // println:(Ljava/lang/String;)V
  #29 = Utf8               Test
  #30 = Utf8               java/lang/Object
  #31 = Utf8               [Ljava/lang/String;
  #32 = Utf8               java/lang/System
  #33 = Utf8               out
  #34 = Utf8               Ljava/io/PrintStream;
  #35 = Utf8               java/io/PrintStream
  #36 = Utf8               println
  #37 = Utf8               (Ljava/lang/String;)V
{
  private int a;
    descriptor: I
    flags: ACC_PRIVATE

  public Test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field a:I
         9: return
      LineNumberTable:
        line 1: 0
        line 2: 4

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=5, args_size=1
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #4                  // String hello world
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: aload_0
         9: astore_1
        10: aload_1
        11: arraylength
        12: istore_2
        13: iconst_0
        14: istore_3
        15: iload_3
        16: iload_2
        17: if_icmpge     39
        20: aload_1
        21: iload_3
        22: aaload
        23: astore        4
        25: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        28: aload         4
        30: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        33: iinc          3, 1
        36: goto          15
        39: return
      LineNumberTable:
        line 9: 0
        line 10: 8
        line 11: 25
        line 10: 33
        line 13: 39
      StackMapTable: number_of_entries = 2
        frame_type = 254 /* append */
          offset_delta = 15
          locals = [ class "[Ljava/lang/String;", int, int ]
        frame_type = 248 /* chop */
          offset_delta = 23

  static native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;
    flags: ACC_STATIC, ACC_NATIVE
}
SourceFile: "Test.java"

11、jhat Java堆内存分析工具

jhat(Java Heap Analysis Tool),是JDK自带的Java堆内存分析工具。可以分析导出的二进制的内存堆dump文件。前面我们使用jmap将JVM中的堆进行打包导出了一个dump文件,而jhat则可以读取解析这个二进制dump文件,同时以网页的形式展示。

这个命令在新版本的JDK中已经被废弃了,推荐使用visualvm

E:\workspace\demo\out\artifacts\demo_jar>jhat -help
Usage:  jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>

        -J<flag>          Pass <flag> directly to the runtime system. For
                          example, -J-mx512m to use a maximum heap size of 512MB
        -stack false:     Turn off tracking object allocation call stack.
        -refs false:      Turn off tracking of references to objects
        -port <port>:     Set the port for the HTTP server.  Defaults to 7000
        -exclude <file>:  Specify a file that lists data members that should
                          be excluded from the reachableFrom query.
        -baseline <file>: Specify a baseline object dump.  Objects in
                          both heap dumps with the same ID and same class will
                          be marked as not being "new".
        -debug <int>:     Set debug level.
                            0:  No debug output
                            1:  Debug hprof file parsing
                            2:  Debug hprof file parsing, no server
        -version          Report version number
        -h|-help          Print this help and exit
        <file>            The file to read

For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".

All boolean options default to "true"

  • -stack false/true

    关闭跟踪对象分配调用堆栈。注意,如果heap dump中的分配位置信息不可用,你必须设置此标识为false。此选项的默认值为true。

  • -refs false/true

    关闭对象的引用跟踪。默认为true。默认情况下,反向指针(指向给定对象的对象,又叫做引用或外部引用)用于计算堆中的所有对象.

  • -port port-number

    设置jhat的HTTP服务器的端口号。默认为7000。

  • -exclude exclude-file

    指定一个数据成员列表的文件,这些数据成员将被排除在"reachable objects"查询的范围之外。举个例子,如果文件列有java.lang.String.value,那么,当计算指定对象"o"的可达对象列表时,涉及java.lang.String.value字段的引用路径将会被忽略掉。

  • -baseline baseline-dump-file

    两个heap dump进行对比。指定一个基线heap dump。在两个heap dump(当前heap dump和基线heap dump)中存在相同对象ID的对象,不会被标记为"new"。其他的对象将被标记为"new"。这在比较两个不同的heap dump时非常有用。

  • -debug int

    设置此工具的调试级别。0意味着没有调试输出。设置的值越高,输出的信息就越详细。

例如:

导出dump文件:
	方法一:jmap -dump:live,format=b,file=Demo.dump 15712
	方法二:jconsole可视化导出
	方法三:jvisualvm可视化导出

启动jhat服务:
	jhat -port 8888 Demo.dump

12、jmc Java任务控制工具

Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。
jmc第一次启动时比较慢,但是这个工具很强大,可以说比visualVM还要强大。不仅可以实时监控,还可以监控一段时间并进行详细分析。


此文章的md文件下载地址:https://files.cnblogs.com/files/chongcheng/java自带工具.zip

posted @ 2020-12-15 15:38  _ME  阅读(1552)  评论(0编辑  收藏  举报