JDK7自带工具目录
1 | C:\Users\Administrator>java -version |
命令 | 说明
—|—
appletviewer | 用于运行并浏览applet小程序。
extcheck | 扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突。
idlj | IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定。IDL意即接口定义语言(Interface Definition Language)。
jar | jar文件管理工具,主要用于打包压缩、解压jar文件。
jarsigner | jar密匙签名工具。
java | Java运行工具,用于运行.class字节码文件或.jar文件。
javac | Java编译工具(Java Compiler),用于编译Java源代码文件。
javadoc | Java文档工具,主要用于根据Java源代码中的注释信息生成HTML格式的API帮助文档。
javafxpackager | JavaFX包装器,用于执行与封装或签名JavaFX应用有关的任务。JDK 8u20已经迁移此工具到javapackager。
javah | Java头文件工具,用于根据Java类生成C/C++头文件和源文件(主要用于JNI开发领域)。
javap | Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件。
javapackager | 执行针对Java应用程序和JavaFX应用程序的打包和签名的任务。包含了javafxpackager的功能。
jcmd | Java 命令行(Java Command),用于向正在运行的JVM发送诊断命令请求。
jconsole | 图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息
jdeps | 用于分析Java class的依赖关系
jdb | Java调试工具(Java Debugger),主要用于对Java应用进行断点调试
jhat | Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。
jinfo | Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。
jjs | 对Nashorn引擎的调用。Nashorn是基于Java实现一个轻量级高性能的JavaScript运行环境。
jmap | Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
jmc | Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。开发者可以使用jmc命令来创建JMC工具。
jps | JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上的HotSpot JVM的Java进程信息。
jrunscript | Java命令行脚本外壳工具(command line script shell),主要用于解释执行javascript、groovy、ruby等脚本语言。
jsadebugd | Java可用性代理调试守护进程(Java Serviceability Agent Debug Daemon),主要用于附加到指定的Java进程、核心文件,或充当一个调试服务器。
jstack | Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
jstat | JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息,包括gc统计信息。
jstatd | jstatd(VM jstatd Daemon)工具是一个RMI服务器应用,用于监测HotSpot JVM的创建和终止,并提供一个接口,允许远程监测工具附加到运行于本地主机的JVM上。
jvisualvm | JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息。
keytool | 密钥和证书管理工具,主要用于密钥和证书的创建、修改、删除等。主要用于获取或缓存Kerberos协议的票据授权票据。允许用户查看本地凭据缓存和密钥表中的条目(用于Kerberos协议)。Kerberos密钥表管理工具,允许用户管理存储于本地密钥表中的主要名称和服务密钥。
native2ascii | 本地编码到ASCII编码的转换器(Native-to-ASCII Converter),用于”任意受支持的字符编码”和与之对应的”ASCII编码和(或)Unicode转义”之间的相互转换。
orbd | 对象请求代理守护进程(Object Request Broker Daemon),它使客户端能够透明地定位和调用位于CORBA环境的服务器上的持久对象。
pack200 | JAR文件打包压缩工具,它可以利用Java类特有的结构,对普通JAR文件进行高效压缩,以便于能够更快地进行网络传输。这是微软提供的对象包装程序,用于对象安装包。
policytool | 策略工具,用于管理用户策略文件(.java.policy)。
rmic | Java RMI 编译器,为使用JRMP或IIOP协议的远程对象生成stub、skeleton、和tie类,也用于生成OMG IDL。
rmid | Java RMI 激活系统守护进程,rmid启动激活系统守护进程,允许在虚拟机中注册或激活对象。
rmiregistry | Java 远程对象注册表,用于在当前主机的指定端口上创建并启动一个远程对象注册表。
schemagen | XML schema生成器,用于生成XML schema文件。
serialver | 序列版本命令,用于生成并返回serialVersionUID。
servertool | Java IDL 服务器工具,用于注册、取消注册、启动和终止持久化的服务器。
tnameserv | Java IDL瞬时命名服务。
unpack200 | JAR文件解压工具,将一个由pack200打包的文件解压提取为JAR文件。
wsgen | XML Web Service 2.0的Java API,生成用于JAX-WS Web Service的JAX-WS便携式产物。
wsimport | XML Web Service 2.0的Java API,主要用于根据服务端发布的wsdl文件生成客户端存根及框架。
xjc | 主要用于根据XML schema文件生成对应的Java类。
Jstat
Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控:
- 类的加载及卸载情况。
- 查看新生代、老生代及持久代的容量及使用情况。
- 查看新生代、老生代及持久代的垃圾收集情况,包括垃圾回收的次数及垃圾回收所占用的时间。
- 查看新生代中Eden区及Survior区中容量及分配情况等。
jstat工具特别强大,它有众多的可选项,通过提供多种不同的监控维度,使我们可以从不同的维度来了解到当前JVM堆的使用情况。详细查看堆内各个部分的使用量,使用的时候必须加上待统计的Java进程号,可选的不同维度参数以及可选的统计频率参数。它主要是用来显示GC及PermGen相关的信息。
命令
1 | jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] |
interval
间隔时间,单位可以是秒或者毫秒,通过指定s或ms确定,默认单位为毫秒。
count
打印次数,如果缺省则打印无数次。
-options
1 | class:用于查看类加载情况的统计。 |
class类加载情况统计
列名 | 说明 |
---|---|
Loaded | 加载了的类的数量 |
Bytes | 加载了的类的大小,单为Kb |
Unloaded | 卸载了的类的数量 |
Bytes | 卸载了的类的大小,单为Kb |
Time | 花在类的加载及卸载的时间 |
compiler查看HotSpot中即时编译器编译情况的统计
列名 | 说明 |
---|---|
Compiled | 编译任务执行的次数 |
Failed | 编译任务执行失败的次数 |
Invalid | 编译任务非法执行的次数 |
Time | 执行编译花费的时间 |
FailedType | 最后一次编译失败的编译类型 |
FailedMethod | 最后一次编译失败的类名及方法名 |
GC JVM中堆的垃圾收集情况的统计
列名 | 说明 |
---|---|
S0C | 新生代中Survivor space中S0当前容量的大小(KB) |
S1C | 新生代中Survivor space中S1当前容量的大小(KB) |
S0U | 新生代中Survivor space中S0容量使用的大小(KB) |
S1U | 新生代中Survivor space中S1容量使用的大小(KB) |
EC | Eden space当前容量的大小(KB) |
EU | Eden space容量使用的大小(KB) |
OC | Old space当前容量的大小(KB) |
OU | Old space使用容量的大小(KB) |
PC | Permanent space当前容量的大小(KB) |
PU | Permanent space使用容量的大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
YGCT | 从应用程序启动到采样时 Young GC 所用的时间(秒) |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(秒) |
GCT | T从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
gccapacity新生代、老生代及持久代的存储容量情况
列名 | 说明 |
---|---|
NGCMN | 新生代的最小容量大小(KB) |
NGCMX | 新生代的最大容量大小(KB) |
NGC | 当前新生代的容量大小(KB) |
S0C | 当前新生代中survivor space 0的容量大小(KB) |
S1C | 当前新生代中survivor space 1的容量大小(KB) |
EC | Eden space当前容量的大小(KB) |
OGCMN | 老生代的最小容量大小(KB) |
OGCMX | 老生代的最大容量大小(KB) |
OGC | 当前老生代的容量大小(KB) |
OC | 当前老生代的空间容量大小(KB) |
PGCMN | 持久代的最小容量大小(KB) |
PGCMX | 持久代的最大容量大小(KB) |
PGC | 当前持久代的容量大小(KB) |
PC | 当前持久代的空间容量大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
gccause用于查看垃圾收集的统计情况(这个和-gcutil选项一样)
如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因
列名 | 说明
—|—
LGCC | 最后一次垃圾收集的原因,可能为“unknown GCCause”、“System.gc()”等
GCC | 当前垃圾收集的原因
gcnew新生代垃圾收集的情况
列名 | 说明 |
---|---|
S0C | 当前新生代中survivor space 0的容量大小(KB) |
S1C | 当前新生代中survivor space 1的容量大小(KB) |
S0U | S0已经使用的大小(KB) |
S1U | S1已经使用的大小(KB) |
TT | Tenuring threshold,要了解这个参数,我们需要了解一点Java内存对象的结构,在Sun JVM中,(除了数组之外的)对象都有两个机器字(words)的头部。第一个字中包含这个对象的标示哈希码以及其他一些类似锁状态和等标识信息,第二个字中包含一个指向对象的类的引用,其中第二个字节就会被垃圾收集算法使用到。 在新生代中做垃圾收集的时候,每次复制一个对象后,将增加这个对象的收集计数,当一个对象在新生代中被复制了一定次数后,该算法即判定该对象是长周期的对象,把他移动到老生代,这个阈值叫着tenuring threshold。这个阈值用于表示某个/些在执行批定次数youngGC后还活着的对象,即使此时新生的的Survior没有满,也同样被认为是长周期对象,将会被移到老生代中。 |
MTT | Maximum tenuring threshold,用于表示TT的最大值。 |
DSS | Desired survivor size (KB).可以参与这里:http://blog.csdn.net/yangjun2/article/details/6542357 |
EC | Eden space当前容量的大小(KB) |
EU | Eden space已经使用的大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
YGCT | 从应用程序启动到采样时 Young GC 所用的时间(单位秒) |
gcnewcapacity新生代的存储容量情况
列名 | 说明 |
---|---|
NGCMN | 新生代的最小容量大小(KB) |
NGCMX | 新生代的最大容量大小(KB) |
NGC | 当前新生代的容量大小(KB) |
S0CMX | 新生代中SO的最大容量大小(KB) |
S0C | 当前新生代中SO的容量大小(KB) |
S1CMX | 新生代中S1的最大容量大小(KB) |
S1C | 当前新生代中S1的容量大小(KB) |
ECMX | 新生代中Eden的最大容量大小(KB) |
EC | 当前新生代中Eden的容量大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
gcold老生代及持久代发生GC的情况
列名 | 说明 |
---|---|
PC | 当前持久代容量的大小(KB) |
PU | 持久代使用容量的大小(KB) |
OC | 当前老年代容量的大小(KB) |
OU | 老年代使用容量的大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(单位秒) |
GCT | 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
gcoldcapacity老生代的存储容量情况
列名 | 说明 |
---|---|
OGCMN | 老生代的最小容量大小(KB) |
OGCMX | 老生代的最大容量大小(KB) |
OGC | 当前老生代的容量大小(KB) |
OC | 当前新生代的空间容量大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(单位秒) |
GCT | 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
gcpermcapacity持久代的存储容量情况
列名 | 说明 |
---|---|
PGCMN | 持久代的最小容量大小(KB) |
PGCMX | 持久代的最大容量大小(KB) |
PGC | 当前持久代的容量大小(KB) |
PC | 当前持久代的空间容量大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
FGC | |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(单位秒) |
GCT | 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
gcutil新生代、老生代及持代垃圾收集的情况
列名 | 说明 |
---|---|
S0 | Heap上的 Survivor space 0 区已使用空间的百分比 |
S1 | Heap上的 Survivor space 1 区已使用空间的百分比 |
E | Heap上的 Eden space 区已使用空间的百分比 |
O | Heap上的 Old space 区已使用空间的百分比 |
P | Perm space 区已使用空间的百分比 |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
YGCT | 从应用程序启动到采样时 Young GC 所用的时间(单位秒) |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(单位秒) |
GCT | 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
printcompilation HotSpot编译方法的统计
列名 | 说明 |
---|---|
Compiled | 编译任务执行的次数 |
Size | 方法的字节码所占的字节数 |
Type | 编译类型 |
Method | 指定确定被编译方法的类名及方法名,类名中使名“/”而不是“.”做为命名分隔符,方法名是被指定的类中的方法,这两个字段的格式是由HotSpot中的“-XX:+PrintComplation”选项确定的。 |
Jmap命令
jmap的用途是为了展示java进程的内存映射信息,或者堆内存详情。
一般使用jps命令,jps用来查看基于HotSpot的JVM里面中,所有具有访问权限的Java
进程的具体状态,包括进程id,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示Java进程,可以把JPS理解为ps的一个子集。
使用jps时,如果没有指定hostid,它只会显示本地环境中所有的Java进程;如果指定了hostid,它就会显示指定hostid上面的java进程,不过这需要远程服务上开启了jstatd服务,可以参看前面的jstatd章节来启动jstad服务。
jmap常用的参数如下。
histo
展示class的内存情况,展示的信息为编号,实例数,字节,类名(存活的对象)。
命令
jmap -histo pid
注意
JVM会先触发gc,然后再统计信息。
heap
展示pid的整体堆信息。根据jps命令,获取JMAP类的执行进程。
命令
jmap -heap pid
执行jmap命令:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51C:\Users\Administrator>jmap -heap 3400
Attaching to process ID 3400, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.76-b04
using thread-local object allocation.
Parallel GC with 4 thread(s) //GC线程
Heap Configuration: //堆内存初始化配置
MinHeapFreeRatio = 0 //设置JVM堆最小空闲比率
MaxHeapFreeRatio = 100 //设置JVM堆最大空闲比率
MaxHeapSize = 2122317824 (2024.0MB) //-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize = 1310720 (1.25MB) //-XX:NewSize=设置JVM堆的‘年轻代’的默认大小
MaxNewSize = 17592186044415 MB //-XX:MaxNewSize=设置JVM堆的‘年轻代’的最大大小
OldSize = 5439488 (5.1875MB) //-XX:OldSize=设置JVM堆的‘老年代’的大小
NewRatio = 2 //-XX:NewRatio=:‘年轻代’和‘老年代’的大小比率
SurvivorRatio = 8 //-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize = 21757952 (20.75MB) //-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
MaxPermSize = 85983232 (82.0MB) //-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space: //Eden区
capacity = 34078720 (32.5MB)
used = 31388544 (29.9344482421875MB)
free = 2690176 (2.5655517578125MB)
92.10599459134616% used
From Space: //一个Survivor区的内存分布
capacity = 5242880 (5.0MB)
used = 565280 (0.539093017578125MB)
free = 4677600 (4.460906982421875MB)
10.7818603515625% used
To Space: //另一个Survivor区的内存分布
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
PS Old Generation //当前的老年代区内存分布
capacity = 88080384 (84.0MB)
used = 8192 (0.0078125MB)
free = 88072192 (83.9921875MB)
0.009300595238095238% used
PS Perm Generation //当前的方法区内存分布
capacity = 22020096 (21.0MB)
used = 2648384 (2.52569580078125MB)
free = 19371712 (18.47430419921875MB)
12.027122860863095% used
1541 interned Strings occupying 141688 bytes.
dump
导出的文件可以供分析用,比如jhat或者mat,以便查找内存溢出原因。
命令
jmap -dump:live,format=b,file=m.bin pid
注意
JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。
permstat
打印(方法区)永久代中classloader的相关信息。
命令
jmap -permstat pid
注意
JVM会去统计perm区的状况,这整个过程也会比较的耗时,并且同样也会暂停应用。
4 内存分析工具(Memory Analyzer Tool,MAT)
修改参数配置
MAT软件版本解压后目录内有个MemoryAnalyzer.ini
文件,该文件里面有个Xmx
参数,该参数表示最大内存占用量,默认为1024m
,根据堆转储文件大小修改该参数即可。
MemoryAnalyzer.ini
中的参数一般默认为-vmargs– Xmx1024m
,这就够用了。假如你机器的内存不大,改大该参数的值,会导致MemoryAnalyzer启动时,报错:Failed to create the Java Virtual Machine
。- 当你导出的dump文件的大小大于你配置的
1024m
(说明1中,提到的配置:-vmargs– Xmx1024m
),MAT输出分析报告的时候,会报错:An internal error occurred during: "Parsing heap dump from XXX”
。适当调大说明1中的参数即可。分析文件
在实际操作过程中采用的是jmap获取堆转储文件,然后导入到本地,然后MAT软件加载。加载后首页如下图,在首页上比较有用的是Histogram和Leak Suspects。 - Histogram可以列出内存中的对象,对象的个数以及大小。
- Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
- Top consumers通过图形列出最大的
object
。 - Leak Suspects通过MA自动分析泄漏的原因。
点击Leak Suspects会在堆转储文件同目录内生成一个Leak Suspects.zip文件,同时也会从首页跳转到Leak Suspects页面。解压该文件后可以通过浏览器打开分析结果。
在Leak Suspects页面会给出可能的内存泄露,如上图所示有三个可能的内存泄露,但是只有第一个是我程序里的,另外两个是jar包或jdk里面的,这个可以不用管。
点击Details进入详情页面。
在详情页面Shortest Paths To the Accumulation Point表示GC root
到内存消耗聚集点的最短路径,如果某个内存消耗聚集点有路径到达GC root
,则该内存消耗聚集点不会被当做垃圾被回收。
在All Accumulated Objects by Class列举了该对象所存储的所有内容。
假如发现对象有可能会溢出,然后我们打开OQL
窗口
执行如下OQL
语句
也就是说这个是null,但是仍然有强引用存在,GC的时候是不能回收的,这样就会出现内存的溢出问题。
为了找到内存泄露,我获取了两个堆转储文件,两个文件获取时间间隔是一天(因为内存只是小幅度增长,短时间很难发现问题)。对比两个文件的对象,通过对比后的结果可以很方便定位内存泄露。
MAT同时打开两个堆转储文件,分别打开Histogram,如下图。在下图中方框1按钮用于对比两个Histogram,对比后在方框2处选择Group By package,然后对比各对象的变化。不难发现heap3.hprof比heap6.hprof少了64个eventInfo对象,如果对代码比较熟悉的话想必这样一个结果是能够给程序员一定的启示的。而我也是根据这个启示差找到了最终内存泄露的位置。