https://blog.csdn.net/u014042066/article/details/78831435
JDK内置工具
JDK自带工具一览表
JDK(Java Development Kit)是Java程序员最核心的开发工具,没有之一。
JDK是一个功能强大的Java开发套装,它不仅仅为我们提供了Java运行环境,还给开发人员提供了许多有用的开发组件(位于bin目录中,如下图所示)。仅仅使用JDK,就能够解决我们在Java开发过程中遇到的许多问题。
下面,我们就按照工具文件名称的英文顺序来逐一介绍JDK内置的工具。
工具名称 |
描述 |
用于运行并浏览applet小程序。 |
|
apt.exe |
注解处理工具(Annotation Processing Tool),主要用于注解处理。 |
扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突。 |
|
idlj.exe |
IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定。IDL意即接口定义语言(Interface Definition Language)。 |
Java访问桥开关(Java Access Bridge switch),用于启用/禁用Java访问桥。Java访问桥内置于Java 7 Update 6及以上版本,主要为Windows系统平台提供一套访问Java应用的API。 |
|
jar文件管理工具,主要用于打包压缩、解压jar文件。 |
|
jar密匙签名工具。 |
|
Java运行工具,用于运行.class字节码文件或.jar文件。 |
|
Java编译工具(Java Compiler),用于编译Java源代码文件。 |
|
Java文档工具,主要用于根据Java源代码中的注释信息生成HTML格式的API帮助文档。 |
|
javafxpackager.exe |
JavaFX包装器,用于执行与封装或签名JavaFX应用有关的任务。 |
Java头文件工具,用于根据Java类生成C/C++头文件和源文件(主要用于JNI开发领域)。 |
|
Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件。 |
|
java-rmi.exe |
Java远程方法调用(Java Remote Method Invocation)工具,主要用于在客户机上调用远程服务器上的对象。 |
Java运行工具,用于运行.class字节码文件或.jar文件,但不会显示控制台输出信息,适用于运行图形化程序。 |
|
Java Web Start,使您可以从Web下载和运行Java应用程序,下载、安装、运行、更新Java应用程序都非常简单方便。 |
|
Java 命令行(Java Command),用于向正在运行的JVM发送诊断命令请求。 |
|
图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息。 |
|
Java调试工具(Java Debugger),主要用于对Java应用进行断点调试。 |
|
Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。 |
|
Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。 |
|
Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。 |
|
jmc.exe |
Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。 |
JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上的HotSpot JVM的Java进程信息。 |
|
Java命令行脚本外壳工具(command line script shell),主要用于解释执行javascript、groovy、ruby等脚本语言。 |
|
jsadebugd.exe |
Java可用性代理调试守护进程(Java Serviceability Agent Debug Daemon),主要用于附加到指定的Java进程、核心文件,或充当一个调试服务器。 |
Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。 |
|
JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息。 |
|
jstatd(VM jstatd Daemon)工具是一个RMI服务器应用,用于监测HotSpot JVM的创建和终止,并提供一个接口,允许远程监测工具附加到运行于本地主机的JVM上。 |
|
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类。 |
Appletviewer
appletviewer.exe主要用于运行并浏览applet小程序。
appletviewer的用法如下图所示:
例如,我们可以直接在命令提示符窗口中输入如下命令来运行JDK demo中的applet程序:
appletviewer http://www.oracle.com/technetwork/java/example1-135910.html
当然,如果你的applet程序位于本地,你也可以指定本地文件路径为url。例如:
appletviewer D:/JDK1.4/java/example1-135910.html
我们还可以为appletviewer指定一些可选的参数:
1. 指定HTML文件使用的编码为"gbk":appletviewer -encoding GBK url。
2. 在Java调试器中启动applet:appletviewer -debug url。
3. 指定-J参数:appletviewer -J-classpath=<classpath> -J-Djava.util.logging.config.file=<logging.properties> url。
ExtCheck
extcheck是JDK自带的jar文件检测工具,主要用于检测指定的jar文件与Java SDK安装的任何扩展之间是否存在版本冲突。在安装一个扩展之前,你可以使用此工具来检测是否已经安装该扩展的相同版本或最新版本。
extcheck工具通过将指定jar文件中清单文件(manifest)的Specification-title和Specification-version头信息与扩展目录中所有的jar文件对应的头信息进行比较,从而检测是否存在版本冲突。
JDK(或JRE)默认的扩展安装目录为jre/lib/ext。extcheck工具通过使用与方法java.lang.Package.isCompatibleWith相同的方式来比较版本号。
如果没有检测出冲突问题,则返回代码为0。
如果扩展目录中任何jar文件的清单文件与指定jar文件有相同的Specification-title以及相同(或更新)的Specification-version版本号,将返回一个非0的错误码。如果指定jar文件的清单文件中没有Specification-title或Specification-version属性,也将返回非0的错误码。
extcheck工具的命令行用法为:
extcheck [-verbose] [-J<runtime flag>] target.jar
其中:
· 可选参数-verbose表示显示详细的检测信息;
· 可选参数-J<runtime flag>可以有多个,用于指定可选的运行时参数,例如:-J-Xms48m。
· 参数target.jar表示指定的jar文件。
Jabswitch
jabswitch,就是Java Access Bridge Switch的简称,用于控制Java访问桥的开/关。
Java访问桥是一种技术,让Java应用程序实现Accessibility API,以供Microsoft Windows系统的辅助技术访问。
启用/禁用Java Access Bridge
Java Access Bridge 内置于Java SE 7 Update 6(7u6)及以上版本。JRE 7u6内置Java Access Bridge 2.0.3。默认情况下,Java Access Bridge没有启用。
启用Java Access Bridge
你可以运行以下命令启用Java Access Bridge:
jabswitch -enable
除此之外,在Windows Vista及以上版本中,你可以通过控制面板启用Java Access Bridge。
1. 点击【开始】 > 【控制面板】 > 【Ease of Access】(轻松访问) > 【Ease of Access Center】(轻松访问中心)。你也可以使用快捷键Windows + U来访问【Ease of Access Center】。
2. 选择【Use the computer without a display】(使用没有显示器的电脑)。
3. 在【Other programs installed】(其他安装程序)部分,选择复选框【Enable Java Access Bridge】(启用Java Access Bridge)。
注意:在启用Java Access Bridge之后,你必须重启你的辅助技术软件和使用Accessibility API的Java应用程序。
禁用Java Access Bridge
你可以运行如下命令禁用Java Access Bridge:
jabswitch -disable
注意:你无法通过Windows 轻松访问中心来禁用Java Access Bridge。
测试Java Access Bridge
你可以通过以下步骤测试Java Access Bridge:
1. 确保启用Java Access Bridge。
2. 安装支持Java Access Bridge的辅助技术产品,例如JAWS 或 NonVisual Desktop Access (NVDA),Windows屏幕阅读器。
3. 运行使用accessibility API的Java应用程序,例如SwingSet2演示程序。确保你的辅助技术产品与Java应用程序工作正常。
获取Java Access Bridge测试工具
Java Access Bridge测试工具Java Monkey和Java Ferret不使用JDK。这些工具内置于Java Access Bridge 2.0.2。你可以通过Java Access Bridge Downloads下载该版本。
故障排除
在64位系统上使用辅助技术
以下列出在64位操作系统上的辅助技术JAWS和NVDA的最低版本(当结合Java Access Bridge使用它们时):
· JAWS: 13及以上版本
· NVDA: 2011及以上版本
注意: 如果你在32位的JRE上使用64位版本的JAWS,JAWS可能无法正确读取值。在这种情况下,请安装64位的JRE并重启JAWS。
仅在私有JRE中使用Java Access Bridge
JDK包含一个私有的JRE。这是运行JDK内置的工具所必需的。私有JRE并没有在系统中注册;没有文件复制到其他位置,也没有创建注册表。不像公共的JRE(你可以从JDK中进行单独安装),私有JRE并不复制Java Access Bridge所需的dll文件到Windows的system32目录。
如果你想要配合私有JRE使用Java Access Bridge,请复制JDK安装目录/jre/bin中名为WindowsAccessBridge*.dll的文件复制到Windows的system32目录。
Jarsigner
jarsigner,jar文件的签名和验证工具,主要用于为jar文件生成签名,并且验证已签名的jar文件的签名信息。
jarsigner的主要用法为:
#生成jar文件的签名
jarsigner [选项] jar文件 别名
#验证已签名的jar文件的签名信息和完整性
jarsigner -verify [选项] jar文件
JAR 功能使得类文件、图像、声音和其它数字化数据可打包到一个文件中,以便更方便快捷地发布。名为 jar 的工具使开发者可以生成 JAR 文件(从技术上来说,任何 zip 文件都可看作为 JAR 文件,尽管由 jar 创建或由 jarsigner 处理时,JAR 文件也包含一个 META-INF/MANIFEST.MF文件)。
数字签名是一个根据某些数据(被“签名”的数据)和实体(人、公司等)的私钥计算出来的位字符串。与手写的签名一样,数字签名有很多有用的特性:
· 其真实性可被校验,方法是使用与生成签名的私钥对应的公钥进行计算。
· 它不可能被伪造(假设私钥没有泄露)。
· 它是已签名数据的函数,因此不能被声明为其它数据的签名。
· 已签名的数据不能被修改;如果被修改了,签名将不再被校验为可信的。
为了给文件生成一个实体的签名,该实体首先必须有一对与它相关的公/私钥对,以及一个或多个鉴别其公钥的证书。证书是由某个实体的数字化方式签发的声明,证明其它实体的公钥是某个特定的值。
jarsigner 使用来自密钥仓库的密钥和证书信息为 JAR 文件生成数字签名。密钥仓库是一个由私钥及其相关的 X.509 证书链(它鉴别相应公钥)组成的数据库。使用 keytool 实用程序来创建和管理密钥仓库。
jarsigner 使用实体的私钥创建签名。已签名的 JAR 文件包含(除了其它东西)一份来自密钥仓库的公钥(它对应于用于为该文件签名的私钥)的证书副本。jarsigner 可以使用已签名的 JAR 文件中的证书(在其签名块文件中)来校验其数字签名。
现在 jarsigner 只能为 JDK 的 jar 工具创建的 JAR 文件或 zip 文件签名(除了它们还有一个 META-INF/MANIFEST.MF 文件以外,JAR 文件与 zip 文件一样)。当 jarsigner 为 zip 文件签名时将自动创建这样的文件。
jarsigner 的缺省行为是签名 JAR(或 zip)文件。使用 -verify 选项将其替换为校验已签名的 JAR 文件。
JDK 1.1 的兼容性
keytool 和 jarsigner 工具完全替代了 JDK 1.1 中提供的 javakey 工具。这些新工具所提供的功能比 javakey 提供的多,包括能够用口令来保护密钥仓库和私钥,以及除了能够生成签名外还可以校验它们。
新的密钥仓库体系结构取代了 javakey 所创建和管理的身份数据库。密钥仓库格式和 1.1 版中 javakey 使用的数据库格式之间没有向后兼容。但是,
· 可以通过 keytool -identitydb 命令将身份数据库中的信息导入密钥仓库。
· jarsigner 可以签名先前已用 javakey 签过名的 JAR 文件。
· jarsigner 可以校验用 javakey 签名的 JAR 文件。因此,它识别并能处理来自 JDK 1.1 身份数据库而不是 JDK 1.2 密钥仓库的签名人别名。
下表解释了在 JDK 1.1.x 中签名的 JAR 文件在 JDK 1.2 中是如何处理的。
JAR 文件类型 |
在 1.1 数据库中的身份 |
从 1.1 数据库 (4) 导入到 1.2 密钥仓库的可信的身份 |
策略文件为 Identity/Alias |
被授予的权利 |
已签名的 JAR |
否 |
否 |
否 |
授予所有代码的缺省权利。 |
未签名的 JAR |
否 |
否 |
否 |
授予所有代码的缺省权利。 |
已签名的 JAR |
否 |
是 |
否 |
授予所有代码的缺省权利。 |
已签名的 JAR |
是/不受信任 |
否 |
否 |
授予所有代码的缺省权利。(3) |
已签名的 JAR |
是/不受信任 |
否 |
是 |
授予所有代码的缺省权利。(1,3) |
已签名的 JAR |
否 |
是 |
是 |
授予所有代码的缺省权利加上策略文件中授予的权利。 |
已签名的 JAR |
是/受信任 |
是 |
是 |
授予所有代码的缺省权利加上策略文件中授予的权利。(2) |
已签名的 JAR |
是/受信任 |
否 |
否 |
所有权利 |
已签名的 JAR |
是/受信任 |
是 |
否 |
所有权利 (1) |
已签名的 JAR |
是/受信任 |
否 |
是 |
所有权利 (1) |
注意:
1. 如果策略文件中提到了 identity/alias,则它必须导入到密钥仓库中,以使策略文件影响授予的权利。
2. 策略文件/密钥仓库组合在身份数据库中优先于可信任的身份。
3. JDK 1.2 中忽略不可信任的身份。
4. 只有可信任的身份才能导入到 JDK 1.2 密钥仓库。
密钥仓库别名
所有密钥仓库实体都须通过唯一的别名来访问。
当使用 jarsigner 签名 JAR 文件时,必须为包含用于生成签名的私钥的密钥仓库实体指定别名。例如,下面命令将使用与别名“duke”(它在“working”目录下的名为“mystore”的密钥仓库中)相关联的私钥为名为“MyJARFile.jar”的 JAR 文件签名。因为没有指定输出文件,它将用已签名的 JAR 文件覆盖 MyJARFile.jar。
jarsigner -keystore /working/mystore -storepass myspass -keypass dukekeypasswd MyJARFile.jar duke
密钥仓库被口令保护,因此必须指定仓库口令(此处为"myspass")。如果在命令行中没有指定它,将提示需要它。同样,私钥也被口令保护在密钥仓库中,因此必须指定该私钥的口令(此处为"dukekeypasswd"),如果没有在命令行中指定它或与仓库口令不一样,将提示需要它。
密钥仓库位置
jarsigner有一个-keystore选项用于指定要使用的密钥仓库的 URL。按默认,密钥仓库储存在用户宿主目录(由系统属性的 "user.home" 决定)中名为 .keystore 的文件中。在 Solaris 系统中 "user.home" 默认为用户的宿主目录。
密钥仓库实现
java.security目前有两个命令行工具(keytool 和 jarsigner),以及一个基于 GUI 的工具(名为 Policy Tool)利用密钥仓库实现。由于密钥仓库是公用的, JDK 用户可编写其它的使用该密钥仓库的安全性应用程序。
有个固有的默认实现,是由 Sun Microsystems 公司提供的。它利用名为“JKS” 的专用密钥仓库类型(格式),将密钥仓库实现为一个文件。它用单个口令保护每个私钥,也用口令(可能为另一个口令)保护整个密钥仓库的完整性。
密钥仓库的实现基于提供者。具体地说,由 keystore 所提供的应用程序接口是借助于“服务提供者接口”(SPI) 来实现的。也就是说,有对应的抽象 KeystoreSpi 类,也是在 java.security 包中,它定义了“提供者”必须实现的服务提供者接口方法(“提供者”指的是一个或一组包,这个或这组包提供了一部份可由 JDK 安全 API 访问的那些服务的具体实现)。因此,要提供密钥仓库实现,客户必须实现提供者并提供 KeystoreSpi 子类实现,如如何为 Java 加密体系结构实现 提供者中所述。
通过使用 KeyStore 类中提供的“getInstance”工厂方法,应用程序可从不同的提供者中挑选不同类型的密钥仓库实现。密钥仓库类型定义密钥仓库信息的存储和数据格式,以及用于保护密钥仓库中的私钥和密钥仓库自身完整性的算法。不同类型的密钥仓库实现是不兼容的。
keytool 可以使用任何基于文件的密钥仓库实现 (它把在命令行中传递给它的密钥仓库位置当成文件处理并将之转换为文件输入流,从该文件输入流中加载密钥仓库信息)。另一方面,jarsigner 和 policytool 工具可从任何可用 URL 指定的位置读取某个密钥仓库。
对于 jarsigner 和 keytool,可以通过 -storetype 选项在命令行中指定密钥仓库类型。对于 策略工具,可通过“编辑”菜单中的“更改密钥仓库”命令来指定密钥仓库类型。
如果没有显式地指定密钥仓库类型,这些工具将只是根据安全属性文件中指定的 keystore.type 属性值来选择密钥仓库实现。安全属性文件名叫 java.security,它位于 JDK 安全属性目录 java.home/lib/security 中,其中java.home 为 JDK 的安装目录。
每个工具都先获取 keystore.type 的值,然后检查所有当前已安装的提供者直到找到实现所要求类型的密钥仓库的提供者为止。然后就使用该提供者的密钥仓库实现。
KeyStore 类定义了名为 getDefaultType 的静态方法,它可让应用程序或 applet 检索 keystore.type 属性的值。以下代码将创建默认密钥仓库类型(此类型由 keystore.type 属性所指定)的实例:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
默认的密钥仓库类型是 "jks" (这是由 "SUN" 提供的密钥仓库实现的专用类型)。它在安全性属性文件中由下面这行进行指定:
keystore.type=jks
要使工具利用非缺省的密钥仓库实现,请更改此行以指定不同的密钥仓库类型。
如果您有这样的提供者包,它给出名为 "pkcs12" 的密钥仓库类型的密钥仓库实现,则可将前面提到的那行改为:
keystore.type=pkcs12
注意: 密钥仓库类型的命名中大小写无关紧要。例如,"JKS" 将被认为是与 "jks" 相同的。
包中提供的 KeyStore 类为访问和修改密钥仓库中的信息提供了相当固定的接口。可以有多个不同的具体实现,其中每个实现都是对某个特定类型的密钥仓库的具体实现。
支持的算法
现在 jarsigner 使用二者都可以签名 JAR 文件。
· 带 SHA-1 报文摘要算法的DSA (数字签名算法),或
· 带 MD5 报文摘要算法的 RSA 算法。
也就是说,如果签名人的公钥和私钥是 DSA 密钥,则 jarsigner 将使用“SHA1withDSA”算法为 JAR 文件签名。如果签名人的密钥是 RSA 密钥,jarsigner 将试图使用“MD5withRSA”算法为 JAR 文件签名。这只有静态地安装了提供“MD5withRSA”算法实现的提供者才可能(来自缺省的“SUN”提供者的“SHA1withDSA”算法总是可用的)。
已签名的 JAR 文件
当 jarsigner 被用于为 JAR 文件签名时,输出的已签名 JAR 文件与输入 JAR 文件完全一样,除了它在 META-INF 目录下有两个附加文件:
· 扩展名为 .SF 的签名文件,以及
· 扩展名为 .DSA 的签名块文件。
这两个文件的基本文件名来自 -sigFile 选项。例如,如果该选项为
-sigFile MKSIGN
则这两个文件分别为MKSIGN.SF和MKSIGN.DSA。
如果命令行中没有-sigfile选项,则 .SF 和 .DSA 文件的基本文件名将是命令行中指定的别名的前 8 个字符,并全部被转换为大写。如果别名少于 8 个字符,将使用整个别名。如果别名中包含签名文件名所不允许的字符,则形成文件名时这样的字符将被转换为下划线 ("_")。合法的字符包括字母、数字、下划线和连字符。
签名 (.SF) 文件
签名文件(.SF 文件)与清单文件相似,后者总是在用 jarsigner 对文件进行签名时包含在 JAR 文件中。也就是说,对于 JAR 文件中包含的每个源文件,.SF 文件与清单文件一样有如下三行:
· 文件名,
· 使用的报文摘要算法 (SHA),以及
· SHA 摘要值。
在清单文件中,SHA 每个源文件的摘要值是源文件中二进制数据的摘要 (散列)。而在 .SF 文件中,给定源文件的摘要值是该源文件的清单文件中的三行的散列。
缺省情况下签名文件还包含一个含有整个清单文件的散列的头。这个头使得可以进行校验优化,如 JAR 文件校验所述。
签名块 (.DSA) 文件
.SF 文件被签名且签名被放入 .DSA 文件。.DSA 文件还包含来自密钥仓库的证书或证书链(被编码到其中),它们鉴别与用于签名的私钥对应的公钥。
JAR 文件校验
如果签名合法,并且签名生成时在 JAR 文件中的文件从此没有更改过,JAR 文件校验将成功。JAR 文件校验包括下列步骤:
1. 校验 .SF 文件本身的签名。
也就是说,校验确保保存在每个签名块 (.DSA) 文件中的签名的确是使用与公钥(其证书或证书链也出现在该 .DSA 文件中)对应的私钥生成的。它还确保该签名是相应签名 (.SF) 文件的合法签名,因此 .SF 文件没有被更改过。
2.
3. 将列在 .SF 文件的每个项中的摘要与清单中相应的部分进行校验。
.SF 文件缺省地包含一个含有整个清单文件的散列的头。该头存在时,校验将检查头中的散列是否匹配清单文件的散列。如果匹配,校验将进行下一步。
4.
如果不匹配,则需一个次优的校验以确保 .SF 文件中的每个源文件信息部分的散列等于清单文件中的相应部分的散列(参见签名 (.SF) 文件)。
5.
保存在 .SF 文件头中的清单文件的散列不等于当前清单文件的散列的一种原因可能是因为生成签名(因此生成 .SF 文件)后一个或多个文件被添加到 JAR 文件中(使用 jar 工具)。当 jar 工具用于添加文件时,清单文件被更改(为新文件添加了节),但 .SF 文件没有更改。如果签名生成时在 JAR 文件中的文件从此没有更改过,校验仍被认为是成功的,这种情况下 .SF 文件的非头部分中的散列与清单文件中相应部分的散列相等。
6.
7. 读取 JAR 中每个在 .SF 文件中有相应项的文件。读取时,计算文件的摘要,然后将结果与清单中该文件的摘要部分进行比较。摘要应相同,否则校验将失败。
如果在校验期间发生了严重的校验错误,则该进程终止并抛出安全异常。它将被 jarsigner捕获并显示。
一个 JAR 文件多个签名
JAR 文件可以被多个人使用 jarsigner 工具进行多次签名,每次为不同的人指定别名,如下:
jarsigner myBundle.jar susan jarsigner myBundle.jar kevin
JAR 文件被多次签名时,产生的 JAR 文件中将有多个 .SF 和 .DSA 文件,每个签名有一对。因此,在上例中,输出的 JAR 文件将包含下列文件:
SUSAN.SF SUSAN.DSA KEVIN.SF KEVIN.DSA
注意: JAR 文件可以有混合签名,有些是 JDK 1.1 javakey 工具生成的,其它是 jarsigner 生成的。也就是说,jarsigner 可用于为先前已使用 javakey 签过名的 JAR 文件签名。
选项
下面列出并说明了各种 jarsigner 选项。注意:
· 所有选项名前都有一个减号(-)。
· 选项可以以任何次序提供。
· 斜体项(选项值)代表必须提供的实际值。
· -keystore、-storepass、-keypass、-sigfile 和 -signedjar 选项仅在为 JAR 文件签名时相关,而不是在校验已签名的 JAR 文件时。同样,别名仅在为 JAR 文件签名时在命令行中指定。
-keystore url
指定密钥仓库的 URL。缺省值是用户的宿主目录中的 .keystore 文件,它由系统属性“user.home”决定。
签名时需要密钥仓库,因此如果没有缺省的(或要使用非缺省的)密钥仓库,就必须明确指定一个。
校验时不需要密钥仓库,但如果指定了一个,或存在缺省的,且 -verbose 选项也被指定了,则将输出该密钥仓库中是否包含了用于校验 JAR 文件的证书的附加信息。
注意:-keystore参数实际上可以是指定的文件名(及路径)而不是 URL,这种情况下它将当作"file:" URL. 也就是说,
-keystore filePathAndName
被当作等价于
-keystore file:filePathAndName
-storetype storetype 指定要被实例化的密钥仓库类型。默认的密钥仓库类型是安全属性文件中 "keystore.type" 属性值所指定的那个类型,由java.security.KeyStore 中的静态方法 getDefaultType 返回。-storepass password指定访问密钥仓库所需的口令。这仅在签名(不是校验)JAR 文件时需要。在这种情况下,如果命令行中没有提供 -storepass 选项,用户将被提示输入口令。
注意: 口令不应在命令行或脚本中指定,除非是为了测试,或在安全系统中。并且,在口令提示下键入口令时将显示出键入的字符,因此不要在其它人面前键入。
-keypass password 指定用于保护密钥仓库项(由命令行中指定的别名标出)的私钥的口令。使用 jarsigner 为 JAR 文件签名时需要该口令。如果命令行中没有提供口令,且所需的口令与密钥仓库的口令不同,则将提示用户输入它。
注意: 口令不应在命令行或脚本中指定,除非是为了测试,或在安全系统中。并且,在口令提示下键入口令时将显示出键入的字符,因此不要在其它人面前键入。
-sigfile file 指定用于生成 .SF 和 .DSA 文件的基本文件名。例如,如果 file 为“DUKESIGN”,则生成的 .SF 和 .DSA 文件将被命名为“DUKESIGN.SF”和“DUKESIGN.DSA”,并将放到已签名的 JAR 文件的“META-INF”目录中。
file 中的字符应来自“a-zA-Z0-9_-”。也就是说,只允许字母、数字、下划线和连字符。注意: .SF 和 .DSA 文件名中小写字母将被转换为大写字母。
如果命令行中没有 -sigfile 选项,则 .SF 和 .DSA 文件的基本文件名将是命令行中指定的别名的前 8 个字符,并全部被转换为大写。如果别名少于 8 个字符,将使用整个别名。如果别名中包含签名文件名所不允许的字符,则形成文件名时这样的字符将被转换为下划线 ("_")。
-signedjar file 指定用于已签名的 JAR 文件的名称。
如果命令行中没有指定名称,将使用输入的 JAR 文件名(要签名的 JAR 文件名);换句话说,该文件将被签名 JAR 文件覆盖。
-verify 如果它出现在命令行中,则指定的 JAR 文件将被校验,而不是签名。如果校验成功,将显示“jar verified”。如果试图校验未签名的 JAR 文件,或校验被不支持的算法(例如未安装 RSA 提供者时使用的 RSA)签名的 JAR 文件,则将有如下显示: "jar is unsigned. (signatures missing or not parsable)"
可以校验使用 jarsigner 或 JDK 1.1 javakey 工具或共用二者签名的 JAR 文件。
有关校验的详细信息,参见 JAR 文件校验。
-certs 如果它与 -verify 和 -verbose 选项一起出现在命令行中,则输出将包括 JAR 文件的每个签名人的证书信息。该信息包括
· 验证签名人公钥的证书的类型名(保存在 .DSA 文件中)
· 如果该证书是 X.509 证书(更准确地说是 java.security.cert.X509Certificate 的实例): 签名人的特征名
密钥仓库也被检查。如果命令行中没有指定密钥仓库值,缺省密钥仓库文件(如果有)将被检查。如果签名人的公钥证书与密钥仓库中的项匹配,则还将显示下列信息:
· 该签名人的密钥仓库项的别名,在圆括号中。如果该签名人实际上来自于 JDK 1.1 身份数据库而不是密钥仓库,则别名将显示在方括号而不是圆括号中。
-verbose 如果它出现在命令行中,则代表“verbose”模式,它使 jarsigner 在 JAR 签名或校验过程中输出额外信息。
-internalsf 过去,JAR 文件被签名时产生的 .DSA(签名块)文件包含一个同时产生的 .SF 文件(签名文件)的完整编码副本。这种做法已被更改。为了减小输出 JAR 文件的整个大小,缺省情况下 .DSA 文件不再包含 .SF 文件的副本。但是如果 -internalsf 出现在命令行中,将采用旧的做法。该选项主要在测试时有用;实际上不应使用它,因为这样将消除有用的优化。
-sectionsonly 如果它出现在命令行中,则 JAR 文件被签名时生成的 .SF 文件(签名文件)将不包括含有整个清单文件的散列的头。它仅包含 与 JAR 中每个单独的源文件相关的信息和散列,如签名 (.SF) 文件所述。
缺省情况下,该头将作为一种优化手段添加。只要该头存在,则无论何时 JAR 被校验,都将首先检查该头中的散列是否真正与整个清单文件的散列匹配。如果匹配,校验将进行下一步。如果不匹配,则有必要执行一个次优的校验,检查 .SF 文件中每个源文件信息部分中的散列是否等于清单文件中相应部分的散列。
有关的详细信息,参见 JAR 文件校验。
该选项主要在测试时有用;实际上不应使用它,因为这样将消除有用的优化。
-Jjavaoption 将指定的 javaoption 串直接传递到 Java 解释器。((jarsigner 实际上是解释器的一个 “wrapper”)。该选项不应含有任何空格。它有助于调整执行环境或内存使用。要获得可用的解释器选项的清单,可在命令行键入 java -h 或 java -X。
程序例子
签名 JAR 文件
假设您有一个 JAR 文件名为“bundle.jar”并且希望使用“working”目录中名为“mystore”的密钥仓库里别名为“Jane”的用户的私钥进行签名。假设密钥仓库口令是“myspass”且 jane 的私钥口令是“j638klm”。您可以使用下列命令为该 JAR 文件签名并将签了名的 JAR 文件命名为“sbundle.jar”:
jarsigner -keystore /working/mystore -storepass myspass -keypass j638klm -signedjar sbundle.jar bundle.jar jane
注意上面的命令中没有指定 -sigfile,因此所产生的要放入已签名 JAR 文件的 .SF 和 .DSA 文件将采用基于别名的缺省名。也就是说,它们将被命名为 JANE.SF 和 JANE.DSA。
如果要根据提示输入仓库口令和私钥口令,可以将上面的命令缩短为
jarsigner -keystore /working/mystore -signedjar sbundle.jar bundle.jar jane
如果要使用的是缺省密钥仓库(它在宿主目录中,名为“.keystore”),则不必指定密钥仓库,如下:
jarsigner -signedjar sbundle.jar bundle.jar jane
最后,如果要使已签名的 JAR 文件简单地覆盖输入的 JAR 文件 (bundle.jar),则不必指定 -signedjar 选项:
jarsigner bundle.jar jane
校验已签名的 JAR 文件
要校验已签名的 JAR 文件,(也就是说验证签名合法且 JAR 文件未被更改过)请使用如下命令:
jarsigner -verify sbundle.jar
如果校验成功,将显示
jar verified.
。否则将出现错误信息。
如果使用 -verbose 选项则将获得更多的信息。下面是用 -verbose 选项使用 jarsigner 的例子及其输出:
jarsigner -verify -verbose sbundle.jar
198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF
199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF
1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA
smk 2752 Fri Sep 26 16:12:30 PDT 1997 AclEx.class
smk 849 Fri Sep 26 16:12:46 PDT 1997 test.class
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
jar verified.
校验证书信息
如果校验时与 -verify 和 -verbose 选项一起指定了 -certs 选项,则输出将包括该 JAR 文件的每个签名人的证书信息,其中包括证书类型、签名人的特征名信息(如果是 X.509 证书),以及括在圆括号中的签名人的密钥仓库别名(如果 JAR 文件中的公钥证书与密钥仓库项中的证书匹配。例如:
jarsigner -keystore /working/mystore -verify -verbose -certs myTest.jar
198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF
199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF
1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA
208 Fri Sep 26 16:23:30 PDT 1997 META-INF/JAVATEST.SF
1087 Fri Sep 26 16:23:30 PDT 1997 META-INF/JAVATEST.DSA
smk 2752 Fri Sep 26 16:12:30 PDT 1997 Tst.class
X.509, CN=Test Group, OU=Java Software, O=Sun Microsystems, L=CUP, S=CA, C=US (javatest)
X.509, CN=Jane Smith, OU=Java Software, O=Sun, L=cup, S=ca, C=us (jane)
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
jar verified.
如果签名人的证书不是 X.509 证书,将没有特征名信息。这种情况下,仅显示证书类型和别名。例如,如果该证书为 PGP 证书,且别名为“bob”,则将显示
PGP, (bob)
校验包含身份数据库签名人的 JAR 文件
如果 JAR 文件已用 JDK 1.1 javakey 工具签名,因此签名人是身份数据库中的别名,则校验输出将包括一个“i”符号。如果 JAR 文件同时被身份数据库中的别名和密钥仓库中的别名二者签名,则将出现“k”和“i”。
当使用了 -certs 选项时,任何身份数据库别名都将显示在方括号中,而不是显示在用于密钥仓库别名的圆括号中。例如:
jarsigner -keystore /working/mystore -verify -verbose -certs writeFile.jar
198 Fri Sep 26 16:14:06 PDT 1997 META-INF/MANIFEST.MF
199 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.SF
1013 Fri Sep 26 16:22:10 PDT 1997 META-INF/JANE.DSA
199 Fri Sep 27 12:22:30 PDT 1997 META-INF/DUKE.SF
1013 Fri Sep 27 12:22:30 PDT 1997 META-INF/DUKE.DSA
smki 2752 Fri Sep 26 16:12:30 PDT 1997 writeFile.html
X.509, CN=Jane Smith, OU=Java Software, O=Sun, L=cup, S=ca, C=us (jane)
X.509, CN=Duke, OU=Java Software, O=Sun, L=cup, S=ca, C=us [duke]
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
i = at least one certificate was found in identity scope
jar verified.
注意别名"duke"在方括号中,这说明它是身份数据库别名,不是密钥仓库别名。
另请参阅
· jar 工具文档
· keytool 工具文档
· Java 教程中的JDK 1.2 的安全性以获得使用 jarsigner 工具的例子
Javadoc
javadoc是一个根据Java源代码中的文档注释生成HTML格式的API文档的工具。
javadoc的用法如下:
C:Documents and SettingsSoftown.cn>javadoc用法: 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> 指定查找用户类文件的位置-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 的路径-Xdocrootparent <url> 将文档注释中出现的所有后跟 /.. 的 @docRoot 替换为 <url>-charset <charset> 用于跨平台查看生成的文档的字符集。-helpfile <file> 包含帮助链接所链接到的文件-linksource 以 HTML 格式生成源文件-sourcetab <tab length> 指定源中每个制表符占据的空格数-keywords 使程序包, 类和成员信息附带 HTML 元标记-stylesheetfile <path> 用于更改生成文档的样式的文件-docencoding <name> 输出编码名称
一般情况下,我们通常使用如下命令:
javadoc [-d 文档存放目录] -author -version cn/softown/Hello.java cn/softown/World.java
我们还可以直接使用包名作为编译参数:
javadoc cn.softown org.apache
Javah
javah,是一个C头文件和存根文件生成器。我们可以使用javah从一个Java类生成C头文件和C源代码文件。这些文件提供了Java和C代码进行交互的纽带。
javah的用法如下:
javah [options] <classes>其中, [options] 包括: -o <file> 输出文件 (只能使用 -d 或 -o 之一) -d <dir> 输出目录 -v -verbose 启用详细输出 -h --help -? 输出此消息 -version 输出版本信息 -jni 生成 JNI 样式的标头文件 (默认值) -force 始终写入输出文件 -classpath <path> 从中加载类的路径 -bootclasspath <path> 从中加载引导类的路径<classes> 是使用其全限定名称指定的(例如, java.lang.Object)。
大多数情况下,我们通常使用如下命令来生成C头文件:
#加载类路径为当前工作目录(其中的类路径.表示当前工作目录)
javah -classpath . cn.softown.HelloJni
javap
javap,是JDK自带的反汇编工具,用于将Java字节码文件反汇编为Java源代码。
javap的用法如下:
用法: javap <options> <classes>可能的选项包括: -help --help -? 打印用法信息 -version 版本信息 -v -verbose 打印附加信息 -l 打印行号和本地变量表 -public 仅显示public类和成员 -protected 显示protected/public类和成员 -package 显示package/protected/public类和成员(默认值) -p -private 显示所有的类和成员 -c 反汇编代码 -s 打印内部类型签名 -sysinfo 显示将被处理的类的系统信息(路径,大小,日期,MD5 哈希值) -constants 显示static final常量 -classpath <path> 指定查找用户类文件的位置 -bootclasspath <path> 覆盖由引导类加载器所加载的类文件的位置
我们通常以如下形式使用javap:
1、不带任何可选参数(如果字节码文件就位于当前工作目录,可以不写类的包名):
#实际上等同于javap -package Person
javap Person
2、反汇编指定目录下的字节码文件:
javap -classpath D:/java/lib cn.softown.Person
3、反汇编字节码文件为JVM可以识别、执行的字节码命令:
javap -c Person
以下是可选参数的详细说明:
-classpath <pathlist>
手动指定用户class字节码文件的存放目录,javap程序将在此目录下查找class文件,多个路径以英文分号分隔。例如:javap -classpath D:java est Person(即使DOS窗口的当前工作目录为其他任意路径,该命令均可正确执行)。
-s
打印变量的内部类型签名,例如:javap -classpath D:java est -s Person。
-extdirs <dirs>
指定javap搜索已安装的java扩展的位置,默认的java扩展的位置为jrelibext。例如:javap -classpath D:java est -extdirs D:javamyext Person
-bootclasspath <pathlist>
指定使用Java底层类加载器(bootstrap class loader)加载的字节码文件的位置。例如:javap -classpath D:java est -bootclasspath D:javacore Person
-verbose
打印方法参数和本地变量的数量以及栈区大小。
-J<flag>
传递运行时标识参数给javap,例如javap -J-version,可以有多个命令,中间以空格隔开。
Javaws
javaws,是Java Web Start的简写。Java Web Start 是一个Java软件,主要用于管理Java应用程序,例如在线下载、安装、运行、更新等。
Java Web Start 软件:
· 提供一种单击一次即可激活应用程序的便捷方法
· 保证您始终运行最新版本的应用程序
· 避免了复杂的安装或升级过程
从 Java 5.0 发布版本开始,Java Runtime Environment (JRE) 中就包含 Java Web Start。这意味着安装 Java 时,将自动安装 Java Web Start。第一次下载采用 Java Web Start 技术的 Java 应用程序时,Java Web Start 软件会自动启动。Java Web Start 软件将整个应用程序高速缓存(存储)到本地计算机上。这样,所有必需的资源都已保存在本地,因此以后再次启动时几乎可以瞬间完成。每次启动应用程序时,Java Web Start 软件组件都会检查应用程序的 Web 站点以确定是否有新的版本;如果有,则立即下载并启动新版本。
以下是javaws的命令行用法:
一般情况下,我们只需要在命令提示符窗口中输入javaws 应用程序jnlp文件的URL即可运行指定的Java应用程序。
Jcmd
jcmd,用于向正在运行的JVM发送诊断信息请求。
jcmd的命令行用法有如下几种:
jcmd [ options ]
jcmd [ pid | main-class ] PerfCounter.print
jcmd [ pid | main-class ] command [ arguments ]
jcmd [ pid | main-class ] -f file
options
命令行选项。请参考选项部分。
pid
接收诊断命令请求的进程ID。该进程必须是一个Java进程。你可以使用jps或jcmd来获取运行于当前计算机上的Java进程列表。
main-class
接收诊断命令请求的进程的main类。匹配进程时,main类名称中包含指定子字符串的任何进程均是匹配的。如果多个正在运行的Java进程共享同一个main类,诊断命令请求将会发送到所有的这些进程中。
command [arguments]
接收诊断命令请求的进程的main类。匹配进程时,main类名称中包含指定子字符串的任何进程均是匹配的。如果多个正在运行的Java进程共享同一个main类,诊断命令请求将会发送到所有的这些进程中。
注意: 如果任何参数含有空格,你必须使用英文的单引号或双引号将其包围起来。 此外,你必须使用转义字符来转移参数中的单引号或双引号,以阻止操作系统shell处理这些引用标记。当然,你也可以在参数两侧加上单引号,然后在参数内使用双引号(或者,在参数两侧加上双引号,在参数中使用单引号)。
举个例子,假设你想要发送一个诊断命令请求到com.example.MyClass name="Value of name argument"。下列3中命令是有效的:
jcmd com.example.MyClass name="Value of name argument"
jcmd com.example.MyClass name="'Value of name argument'"
jcmd com.example.MyClass name='"Value of name argument"'
下列两种命令是无效的:
jcmd com.example.MyClass name=Value\ of\ name\ argument
jcmd com.example.MyClass name="Value of name argument"
Perfcounter.print
打印目标Java进程上可用的性能计数器。性能计数器的列表可能会随着Java进程的不同而产生变化。
-f file
从文件file中读取命令,然后在目标Java进程上调用这些命令。在file中,每个命令必须写在单独的一行。以"#"开头的行会被忽略。当所有行的命令被调用完毕后,或者读取到含有stop关键字的命令,将会终止对file的处理。
描述
jcmd 是一个向支持该功能的JVM发送诊断命令请求的工具。
使用不带参数或参数-l,jcmd 将打印运行的Java进程的列表信息,其中包括进程ID、main类和它们的命令行参数。
如果在命令行中指定进程ID,jcmd 将向该进程ID的Java进程发送至诊断命令请求。
如果在命令行中指定main类,jcmd 将向main类包含该子字符串的所有Java进程发送诊断命令请求。
如果使用PerfCounter.print 参数,jcmd 打印目标Java进程上可用的性能计数器。
如果使用-f 选项参数,jcmd 将向目标Java进程发送file中存储的诊断命令。
选项参数
jcmd的选项参数是互斥的(不能同时使用)。你可以直接使用如下命令名称。
-l
打印正在运行的Java进程的列表信息,包括进程ID、main类以及它们的命令行参数。
-h
打印帮助信息。
-help
打印帮助信息。
另请参阅
· jps
JConsole
JConsole是一个遵循JMX(Java Management Extensions)规范的图形用户界面的监测工具,主要用于监控并提供运行于Java平台的应用程序的性能和资源占用信息。
在Java SE 6中,JConsole已经升级为Windows和GNOME桌面现行的视觉感观效果(其他平台将使用Java图形化的视觉感官),本文中的截图取自运行于Windows XP系统的界面实例。
JConsole可执行文件位于JDK_HOME/bin目录中(JDK_HOME表示JDK的安装目录)。如果该目录路径位于path环境变量中,你可以直接在命令提示符中输入jconsole来启动JConsole,如果该目录路径不在path环境变量中,你必须输入路径全称(在Windows系统中,你也可以直接双击jconsole.exe来启动JConsole)。
你可以使用JConsole来监测本地应用(本机上的Java应用)和远程应用(其他计算机上的Java应用)。
注意:使用JConsole监控本地应用对于开发和创建原型非常有用,但是不推荐在生产环境上使用,因为JConsole自身会占用大量的系统资源。如果想要隔离JConsole程序与被监测的平台,推荐使用远程监控。
Jdb
jdb,意即Java Debugger,主要用来帮助我们查找并修复Java程序中的bug。
用法摘要
jdb的用法摘要如下:
jdb [ options ] [ class ] [ arguments ]
命令行选项,详见下面的介绍。
class
开始调试的类名称。
arguments
传递给class的main()方法的参数。
描述
Java调试器,jdb,是一个Java类的简单调试器。它是Java平台调试器体系结构的一个演示,该体系结构提供对本地或远程JVM的检查和调试。
开始一个jdb会话
我们有许多种方式来启动一个jdb会话。最常用的方法是jdb以待调试的应用程序的main类来运行一个新的JVM。在命令行中,我们可以替换命令中的java为jdb,从而实现该目的。例如,如果你的应用程序main类为MyClass,你可以使用如下jdb命令来调试它:
jdb MyClass
当使用这种方式启动时,jdb将调用另一个带任意指定参数的JVM,加载指定的类,并在执行这些类的第一个指令之前停止VM。
使用jdb的另一种方式是将其附加到已经运行的JVM中,想要使用jdb调试的JVM必须使用下列选项参数来启动。这些选项参数会加载过程调试库,并指定创建哪种连接。
-agentlib:jdwp=transport=dt_shmem,server=y,suspend=n
例如,下列命令将会运行MyClass应用程序,并允许jdb稍后连接它。
java -agentlib:jdwp=transport=dt_shmem,address=jdbconn,server=y,suspend=n MyClass
你可以使用如下命令将jdb附加到JVM:
jdb -attach jdbconn
注意,在这个例子中,我们并没有在jdb命令中中指定"MyClass",因为jdb连接到的是一个现有的虚拟机,而不是运行一个新的虚拟机。我们有许多种方式可以将调试器连接到虚拟机,而jdb支持所有的这些方式。Java平台调试器体系结构有一个与这些连接选项相关的附加文档。关于启动一个J2SE 1.4.2或更早版本的虚拟机,并与jdb进行搭配使用的相关信息,请查看1.4.2文档。
基本的jdb命令
以下是基本的jdb命令列表。Java调试器支持jdb帮助命令列出的其他命令。
help, or ?
最重要的jdb命令,用于显示带简要说明的公认的命令列表。
run
在启动jdb,并且设置任何必要的断点之后,你可以使用此命令来启动待调试的应用程序的执行。只有使用jdb运行待调试的应用程序时(与附加到现有的虚拟机的做法相反),该命令才可用。
cont
在一个断点、异常或者步骤之后,继续待调试的应用程序的执行。
显示Java对象和原生值。 对于原生类型的变量或字段而言,将会打印实际的值;对于对象而言,将打印一个简单的描述。请查看下方的dump命令以获取关于对象的更多信息。
注意: 为了显示本地变量,包含的类必须使用javac -g 选项进行编译。
print支持多种包含方法调用的简单Java表达式,例如:
· print MyClass.myStaticField
· print myObj.myInstanceField
· print i + j + k (i, j, k are primities and either fields or local variables)
· print myObj.myMethod() (if myMethod returns a non-null)
· print new java.lang.String("Hello").length()
dump
对于原生值而言,该命令等同于print。对于对象而言,它会打印对象中每个定义的字段的当前值。静态字段和实例字段均包含在内。
threads
列出当前正在运行的线程,并打印出每个线程的名称和当前状态,以及可用于其他命令的索引值。例如:
4. (java.lang.Thread)0x1 main running
在这个示例中,线程的索引为4,该线程是java.lang.Thread的一个实例,线程名称为"main",该线程正在运行。
thread
选择一个线程作为当前线程。许多jdb命令都是基于当前线程的设置。该线程可以用上面threads命令中描述的索引值来指定。
where
不带参数的where将输出当前线程的堆栈信息。where all 将输出当前线程组中所有线程的堆栈信息。where threadindex 将输出指定索引的线程的堆栈信息。
如果当前线程被挂起(通过诸如一个断点的事件或挂起命令来实现),使用print和dump变量将打印本地变量和字段。向上向下命令可以选择当前的栈帧。
断点
在jdb中,我们可以在指定行号或方法的第一个指令处设置断点,例如:
· stop at MyClass:22 (在MyClass第22行源代码的第一个指令处设置一个断点)
· stop in java.lang.String.length (在java.lang.String.length方法的开始位置设置一个断点)
· stop in MyClass.<init> (<init>标识MyClass的构造函数)
· stop in MyClass.<clinit> (<clinit>标识MyClass的静态初始化代码)
如果一个方法被重载,你也必须指定它的参数类型,以便于断点能够选择适当的方法。例如:MyClass.myMethod(int,java.lang.String),或者MyClass.myMethod()。
我们可以使用语法类似于clear MyClass:45的clear命令来删除断点。使用不带参数的clear命令可以显示当前设置的所有断点列表。使用cont命令可以继续向下执行。
步进
step命令用于向前执行到当前栈帧或被被调用方法的下一行,next命令用于向前执行到当前栈帧的下一行。
异常
如果发生了一个没有被catch语句捕获的异常,虚拟机通常会打印该异常的追踪信息并退出程序。当运行于jdb之下时,无论如何,抛出的异常都会被控制返回到jdb上,然后,你可以使用jdb来诊断异常的原因。
使用catch命令让待调试的应用程序在其他抛出异常的位置暂停,例如:catch java.io.FileNotFoundException或catch mypackage.BigTroubleException。指定类(或子类)实例的任何异常都将在异常的抛出位置暂停应用程序。
ignore命令用于取消上一个catch命令的作用效果。
注意:ignore命令不会导致待调试的虚拟机忽略指定的异常,而是仅作用于调试器。
命令行选项
当你使用在命令行中使用jdb时,jdb接受大多数与java命令相同的选项参数,包括-D,-classpath,和-X<option>等。
jdb接受如下额外选项:
-help
显示帮助信息。
-sourcepath <dir1:dir2:...>
指定源代码文件的搜索路径。如果此选项未指定,则默认为"."。
-attach <address>
使用默认的连接机制,将调试器附加到之前运行的虚拟机上。
-listen <address>
使用标准器连接器在指定的地址等待正在运行的虚拟机进行连接。
-listenany
使用标准连接器在任何可用的地址等待正在运行的虚拟机进行连接。
-launch
当启动jdb时,立即启动待调试的应用程序。此选项不需要使用运行命令。待调试的应用程序将会运行,然后在加载初始化应用类之前暂停。 此时,你可以设置任何必要的断点,然后使用cont来继续执行。
-listconnectors
列出在此虚拟机上可用的连接器。
-connect <connector-name>:<name1>=<value1>,...
使用命名的连接器和列出的参数值连接目标虚拟机。
-dbgtrace [flags]
打印正在调试的jdb的相关信息。
-tclient
以Java HotSpot虚拟机(客户端)模式运行应用程序。
-tserver
以Java HotSpot虚拟机(服务器)模式运行应用程序。
-Joption
传递选项参数给Java虚拟机,并用于运行jdb。(Java虚拟机程序的选项参数使用运行命令来传递。) 例如,-J-Xms48m 设置启动内存为48MB。
其他选项支持连接调试器的替代机制和虚拟机调试。Java平台调试器体系结构提供了关于连接方案的附加文档。
转发到被调试的进程的选项参数
-v -verbose[:class|gc|jni]
启用冗余模式。
-D<name>=<value>
设置系统属性。
-classpath <directories separated by ":">
列出用于查找类的目录。
-X<option>
非标准的目标虚拟机选项。
另请查阅
javac,java,javah,javap,javadoc。
Jhat
jhat(Java Heap Analysis Tool),是JDK自带的Java堆内存分析工具。
用法摘要
jhat的命令行用法如下:
jhat [ options ] <heap-dump-file>
参数
选项参数.如果使用,请直接跟在命令名称之后。
heap-dump-file
指定用于浏览的Java二进制heap dump文件。对于一个包含多个heap dump的dump文件,你可以在文件名称后面追加"#<number>"来指定文件中的某个dump,例如:foo.hprof#3。
描述
jhat命令解析一个java heap dump文件并启动一个web服务器。jhat使得你可以使用自己喜欢的web浏览器浏览heap dump。jhat支持预先设计的查询语言(例如'show all instances of a known class "Foo"')以及OQL(对象查询语言) -- 一种用于查询heap dump的、类似于SQL的查询语言。你可以通过jhat显示的OQL帮助页面查看关于OQL的帮助信息。在使用默认端口的情况下,OQL的帮助信息位于http://localhost:7000/oqlhelp/。
有以下几种方式可以生成一个Java heap dump:
· 使用jmap -dump选项获取一个运行时的heap dump。
· 使用jconsole选项通过运行时的HotSpotDiagnosticMXBean获取一个heap dump。
· 通过指定-XX:+HeapDumpOnOutOfMemoryErrorVM选项,在抛出OutOfMemoryError错误时,将会生成一个heap dump。
· 使用hprof。
注意:此工具具有实验性质的,并不保证在未来版本的JDK中可用。
选项
-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)中存在相同对象ID的对象,不会被标记为"new"。其他的对象将被标记为"new"。这在比较两个不同的heap dump时非常有用。
-debug int
设置此工具的调试级别。0意味着没有调试输出。设置的值越高,输出的信息就越详细。
-version
报告版本号并退出。
-h
输出帮助信息并退出。
-help
输出帮助信息并退出。
-J<flag>
将运行时参数传递给运行jhat的JVM。例如,-J-Xmx512m设置使用的最大堆内存大小为512MB。
另请参阅
Jinfo
jinfo(Java Configuration Information),主要用于查看指定Java进程(或核心文件、远程调试服务器)的Java配置信息。
用法摘要
#指定进程号(pid)的进程
jinfo [ option ] pid
#指定核心文件
jinfo [ option ] <executable <core>
#指定远程调试服务器
jinfo [ option ] [server-id@]<remote-hostname-or-IP>
参数
选项参数是互斥的(不可同时使用)。想要使用选项参数,直接跟在命令名称后即可。
pid
需要打印配置信息的进程ID。该进程必须是一个Java进程。想要获取运行的Java进程列表,你可以使用jps。
executable
产生核心dump的Java可执行文件。
core
需要打印配置信息的核心文件。
remote-hostname-or-IP
远程调试服务器的(请查看jsadebugd)主机名或IP地址。
server-id
可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。
描述
jinfo用于打印指定Java进程、核心文件或远程调试服务器的Java配置信息。配置信息包括Java系统属性、Java虚拟机命令行标识参数。如果给定的进程运行于64位的虚拟机上,你可能需要使用指定-J-d64选项,例如:
jinfo -J-d64 -sysprops pid
注意 - 此工具是不受支持的,不确定在未来版本的JDK中是否可用。在不存在dbgeng.dll的Windows系统中,需要安装'Windows调试工具',才能让这些工具工作。另外,PATH环境变量应该包含目标进程或Crash Dump文件产生目录使用的jvm.dll的路径。
例如,set PATH=<jdk>jreinclient;%PATH%。
选项
<no option>
打印命令行标识参数和系统属性键值对。
-flag name
打印指定的命令行标识参数的名称和值。
-flag [+|-]name
启用或禁用指定的boolean类型的命令行标识参数。
-flag name=value
为给定的命令行标识参数设置指定的值。
-flags
成对打印传递给JVM的命令行标识参数。
-sysprops
以键值对形式打印Java系统属性。
-h
打印帮助信息。
-help
打印帮助信息。
另请参阅
· jps
Jmap
jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。
用法摘要
#指定进程号(pid)的进程
jmap [ option ] <pid>
#指定核心文件
jmap [ option ] <executable <core>
#指定远程调试服务器
jmap [ option ] [server-id@]<remote-hostname-or-IP>
参数
选项参数是互斥的(不可同时使用)。想要使用选项参数,直接跟在命令名称后即可。
pid
需要打印配置信息的进程ID。该进程必须是一个Java进程。想要获取运行的Java进程列表,你可以使用jps。
executable
产生核心dump的Java可执行文件。
core
需要打印配置信息的核心文件。
remote-hostname-or-IP
远程调试服务器的(请查看jsadebugd)主机名或IP地址。
server-id
可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。
描述
jmap用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
如果给定的进程运行于64位的虚拟机上,你可能需要使用指定-J-d64选项,例如:
jmap -J-d64 -heap pid
注意 - 此工具是不受支持的,不确定在未来版本的JDK中是否可用。在不存在dbgeng.dll的Windows系统中,需要安装'Windows调试工具',才能让这些工具工作。另外,PATH环境变量应该包含目标进程或Crash Dump文件产生目录使用的jvm.dll的路径。
例如,set PATH=<jdk>jreinclient;%PATH%。
选项
<no option>
如果使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。
-dump:[live,]format=b,file=<filename>
以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。
-finalizerinfo
打印等待终结的对象信息。
-heap
打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和generation wise heap usage。
-histo[:live]
打印堆的柱状图。其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个'*'前缀。如果指定了live子选项,则只计算活动的对象。
-permstat
打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。
-F
强制模式。如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。
-h
打印帮助信息。
-help
打印帮助信息。
-J<flag>
指定传递给运行jmap的JVM的参数。
Jps
jps(JVM Process Status Tool),主要用于显示Java进程的状态信息。
用法摘要
jps [ options ] [ hostid ]
命令行选项。
指定为其生成进程报告的主机的主机标识符。hostid可能包括表示通讯协议、端口号以及其他实现特定数据的可选组件。
描述
jps工具用于列出目标系统上安装的HotSpot JVM。此工具仅限于报告JVM在其访问权限内的相关信息。
如果运行jps时没有指定hostid参数,它将查找本地主机上安装的JVM。如果在启动jps的同时指定了一个hostid,则它会使用指定的协议和端口,在hostid所表示的主机上查找JVM。一个jstatd进程被认为正运行于目标主机上。
对于在目标系统上找到的每个JVM而言,jps命令将报告本地虚拟机的标识符,或者lvmid。lvmid通常是,但不一定是,Java进程的操作系统进程标识符。如果没有指定选项参数,jsp将列出每个Java应用程序的lvmid,并紧随在简短格式的应用程序类名或jar文件名称之后。简短格式的类名或jar文件名会忽略掉类的包名信息或jar文件的路径信息。
jps命令使用java启动器来查找类名以及传递给main方法的参数。如果使用自定义启动器来启动JVM,类名(或jar文件名称)和传递给main方法的参数将不可用。在这种情况下,jps命令将会针对类名或jar文件名称和传递给main方法的参数输出"Unknown"字符串。
使用jps命令产生的JVM列表可能受限于授予运行该命令的角色权限。该命令只会列出取决于操作系统特定访问控制机制的具有访问权限的JVM。
注意:此工具是不受支持的,并且无法确定在未来版本的JDK中是否可用。目前,该工具无法在Windows 98和Windows ME平台上使用。
选项
jps命令支持许多修改该命令输出的选项。以后,这些选项可能随时会被更改或移除。
-q
抑制类名、jar文件名称以及传递给main方法的参数的输出,仅产生本地虚拟机标识符的列表。
-m
输出传递给main方法的参数。嵌入式JVM的输出可能为null。
-l
输出应用程序main类的完整包名,或者应用程序jar文件的路径全称。
-v
输出传递给JVM的参数。
-V
输出通过标识文件(.hotspotrc文件或-XX:Flags=<filename>参数指定的文件)传递给JVM的参数。
-Joption
传递选项参数给被javac调用的java启动程序。例如,-J-Xms48m设置启动内存为48 MB。使用-J将选项参数传递给执行Java应用程序的底层虚拟机,这是一种常见惯例。
主机标识符
主机标识符,或hostid,是一个表示目标系统的字符串。hostid字符串的语法与URI的语法基本一致:
[protocol:][[//]hostname][:port][/servername]
protocol
通讯协议。如果protocol被省略,并且没有指定主机名称,则默认协议为一个特定于平台的优化的本地协议。如果protocol被省略,并且指定了主机名称,则默认的协议为rmi。
hostname
表示目标主机的主机名或IP地址。如果主机名被省略,那么目标主机就是本地主机。
port
与远程服务器通讯的默认端口。如果主机名被省略,或者协议指定为一个最佳优化的本地协议,那么端口将被忽略掉。否则,端口参数的处理是一个特定的实现。对于默认的rmi协议,port将采用远程主机上rmiregistry端口号。如果端口被省略,并且协议为rmi,那么将使用默认的rmiregistry端口(1099)。
servername
该参数的处理取决于实现。对于经过优化的本地协议,该字段会被忽略。对于rmi协议,该参数是远程主机上表示RMI远程对象名称的一个字符串。请参考jstatd命令的-n选项。
输出格式
jps命令的输出遵循以下模式:
lvmid[ [classname|JARfilename| "Unknown"] [arg* ] [jvmarg* ] ]
所有的输出标记均使用空格隔开。当尝试映射参数到它们的实际位置参数时,包含嵌入的空格的参数将引入歧义。
注意:由于在未来版本中输出格式可能更改,因此不建议编写脚本来解析jps输出。如果你选择编写解析jps输出的脚本,可能需要针对此工具的未来版本修改这些脚本。
示例
本节提供jps命令的示例。
列出本地主机上的JVM:
jps
18027 Java2Demo.JAR
18032 jps
18005 jstat
列出远程主机上的JVM:
本示例假定jstat服务器和它内部的RMI注册表(或远程主机上单独的外部rmiregistry进程)在默认端口上运行(端口为1099)。它也假定本地主机具有适当的访问远程主机的权限。本示例也包含-l选项参数,用于输出详细格式的类名或jar文件名。
jps -l remote.domain3002 /opt/j2sdk1.5.0/demo/jfc/Java2D/Java2Demo.JAR
2857 sun.tools.jstatd.jstatd
列出使用非默认端口的RMI注册表的远程主机上的JVM:
本示例假定远程主机上运行的jstatd服务器使用绑定端口2002的内部RMI注册表。本示例也使用-m选项参数,以包括每个列出的Java应用的main方法的传递参数。
jps -m remote.domain:20023002 /opt/j2sdk1.5.0/demo/jfc/Java2D/Java2Demo.JAR
3102 sun.tools.jstatd.jstatd -p 2002
另请参阅
· jstat - the Java virtual machine Statistics Monitoring Tool
· rmiregistry - the Java Remote Object Registry
Jrunscript
jrunscript,是一个命令行脚本外壳,主要用于解释执行javascript、groovy、ruby等脚本语言。
用法摘要
jrunscript [options] [ arguments... ]
参数
选项。如果使用,请直接跟在命令名称的后面。
参数。如果使用,请直接跟在命令名称或选项的后面。
描述
jrunscript是一个命令行脚本外壳。jrunscript支持交互模式(read-eval-print)和批处理模式(-f选项)的脚本执行。这是一个脚本语言的独立外壳。默认情况下,使用JavaScript,但是我们可以使用-l选项来指定不同的语言。通过Java与脚本语言的通讯,jrunscript支持"探索性编程"风格。
注意:此工具具有实验性质,在未来版本的JDK中可能不可用。
选项
-classpath path
指定脚本访问的用户类文件(.class)的位置。
-cp path
-classpath的同义词。
-Dname=value
设置一个Java系统属性。
-J<flag>
直接传递标识参数<flag>到运行jrunscript的JVM上。
-l language
使用指定的脚本语言。默认情况下,使用JavaScript。注意,为了使用其他的脚本语言,你也需要使用-cp或-classpath选项来指定对应脚本引擎的jar文件。
-e script
评估给定的脚本。在命令行中,该选项完全可以用来运行指定的"一句话"脚本。
-encoding encoding
指定读取脚本文件时使用的字符编码。
-f script-file
评估给定的脚本文件(批处理模式)。
-f -
读取并评估来自标准输入的脚本(交互模式)。
-help
输出帮助信息并退出。
-?
输出帮助信息并退出。
-q
列出所有可用的脚本引擎,并退出。
参数
如果存在[arguments...],并且没有使用-e或-f选项,那么第一个参数就是脚本文件,剩余的参数就作为脚本的参数。如果存在[arguments..],并使用了-e或-f选项,那么所有的[arguments..]都将作为脚本的参数。如果[arguments..]、-e和-f选项都不存在,则使用交互模式。我们可以通过一个名为"arguments"的字符串数组类型的引擎变量来使用脚本参数。
示例
执行内联脚本
jrunscript -e "print('hello world')"
jrunscript -e "cat('http://www.example.com')"
使用执行的语言并评估给定的脚本文件
jrunscript -l js -f test.js
交互模式
jrunscript
js> print('Hello World
');
Hello World
js> 34 + 55
89.0
js> t = new java.lang.Thread(function() { print('Hello World
'); })
Thread[Thread-0,5,main]
js> t.start()
js> Hello World
js>
运行带脚本参数的脚本文件
jrunscript test.js arg1 arg2 arg3
test.js是一个脚本文件,arg1,arg2和arg3是传递给脚本的脚本参数。脚本可以使用"arguments"数组来访问这些参数。
另请参阅
如果使用JavaScript语言,那么在评估任何用户定义的脚本之前,jrunscript会初始化特定的内置函数和对象。JavaScript内置请参见文档jsdocs。
Jstack
jstack,是一个堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
用法摘要
#指定进程号(pid)的进程
jstack [ option ] <pid>
#指定核心文件
jstack [ option ] <executable <core>
#指定远程调试服务器
jstack [ option ] [server-id@]<remote-hostname-or-IP>
参数
选项参数是互斥的(不可同时使用)。想要使用选项参数,直接跟在命令名称后即可。
pid
需要打印配置信息的进程ID。该进程必须是一个Java进程。想要获取运行的Java进程列表,你可以使用jps。
executable
产生核心dump的Java可执行文件。
core
需要打印配置信息的核心文件。
remote-hostname-or-IP
远程调试服务器的(请查看jsadebugd)主机名或IP地址。
server-id
可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。
描述
jstack打印给定Java进程或核心文件、远程调试服务器的Java线程的堆栈跟踪信息。对于每个Java帧而言,jstack将打印类名全称、方法名称、'bci'(byte code index/字节码索引)和行号中可用的信息。使用-m选项,jstack会打印随着'pc'(program counter/程序计数器)而变化的所有线程的Java帧和本地帧。对于每个本地帧而言, 将打印离'pc'最近的本地符号(如果可用的话)。C++ mangled names are not demangled.To demangle C++ names, the output of this command may be piped to c++filt.
注意 - 此工具是不受支持的,无法确定在未来版本的JDK中是否可用。jstack目前不适用于Windows平台或Linux安腾平台。
选项
-m
打印混合模式(Java和本地C/C++帧)的堆栈跟踪信息。
-h
打印帮助信息。
-help
打印帮助信息。
另请参阅
· pstack(1)
· c++filt(1)
· jps
已知的bug
混合模式的堆栈跟踪信息,即-m选项,无法在远程调试服务器上工作。
Jstat
jstat,是Java虚拟机的统计监测工具,主要用于显示JVM的性能统计性能。
用法摘要
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
单个常规的命令行选项(-help,-options,或-version)。
outputOptions
一个或多个输出选项,由一个statOption加上任意的-t,-h和-J选项。
vmid
虚拟机标识符,一个表示目标JVM的字符串。常规语法是:
[protocol:][//]lvmid[@hostname[:port]/servername]
vmid字符串的语法与URI的语法基本保持一致。vmid可以是一个代表本地JVM的简单整数,也可以是一个指定了通讯协议、端口号以及其他特定实现的值的复杂结构。请查看虚拟机标识符了解更多细节。
interval[s|ms]
指定单位(秒/s或毫秒/ms)的采样时间间隔,必须是一个正整数。默认单位为毫秒。如果指定了该选项参数,每过指定的间隔时间,jstat就会产生一次输出。
count
显示的样本数,必须是一个正整数。默认值为无限大;也就是说,jstat将会一直显示统计信息,直到目标JVM终止或者jstat命令被终止。
描述
jstat工具用于显示一个HotSpot Java虚拟机(JVM)的性能统计信息。通过下面描述的虚拟机标识符或vmid选项来标识目标JVM。
注意:此工具是不受支持的,并且无法确定在未来版本的J2SE JDK中是否可用。此工具目前不适用于Windows 98和Windows ME平台。
虚拟机标识符
vmid字符串的语法与URI的语法基本保持一致:
[protocol:][//]lvmid[@hostname][:port][/servername]
protocol
通讯协议。如果protocol被省略并且未指定主机名,则默认协议是一个特定于平台的优化的本地协议。如果protocol被省略并指定了主机名,则默认协议为rmi。
lvmid
目标JVM的本地虚拟机标识符。lvmid是一个特定平台的值,并在系统上唯一地标识一个JVM。lvmid是虚拟机标识符唯一的必需组件。lvmid通常是(但并不一定是)目标JVM进程在该操作系统上的进程标识符。你可以使用jps命令来确定lvmid。另外,在Unix平台上你可以使用ps命令来确定lvmid,在Windows平台上,你可以使用Windows任务管理器来确定lvmid。
hostname
表示目标主机的主机名或IP地址。如果hostname被省略,则默认目标主机为本地主机。
port
与远程服务器通讯的默认端口号。如果hostname被省略,或者protocol指定了一个优化的本地协议,那么port将被忽略。否则,端口参数的处理是一个特定的实现。对于默认的rmi协议来说,port表示远程主机上rmiregistry的端口号。如果port被省略,并且protocol为rmi,那么将使用默认的rmiregistry端口(1099)。
servername
该参数的处理取决于具体实现。对于优化的本地协议而言,该字段将会忽略。对于rmi协议而言,它代表远程主机上RMI远程对象的名称。
选项
jstat命令支持两种类型的选项,常规选项和输出选项。常规选项使得jstat显示简单的用法和版本信息。输出选项决定统计输出的内容和格式。
注意:所有的选项,以及它们的功能作用可能会在未来的版本中变更或移除。
常规选项
如果你指定了一个常规选项,你就不能再指定其他的选项或参数。
-help
显示帮助信息。
-version
显示版本信息。
-options
显示统计选项列表。查看下面的输出选项部分。
输出选项
如果你没有指定常规选项,那么你可以指定输出选项。输出选项用于确定jstat输出的内容和格式,它由一个statOption选项,加上任意的其他输出选项(-h,-t,和-J)组成。statOption必须在第一位置。
输出将被格式化为一个表格,其中的列以空白隔开。头部行拥有标题和描述列。使用-h选项来设置表格头的显示频率。不同选项之间的列标题名称通常是一直的。一般情况下,如果两个选项提供了同一名称的列,那么两个列的数据源是相同的。
使用-t选项来显示一个时间戳列,该列将会是输出的第一个列,标题为Timestamp。Timestamp列包含从目标JVM启动开始计算的已过去的时间,单位为秒。时间戳的精确度取决于多种因素,变化主要取决于高负载系统上的线程调度延迟。
分别使用interval和count参数来确定jstat显示输出的频率和次数。
注意:由于在未来版本中输出格式可能变更,因此不建议编写脚本来解析jstat输出。如果你选择编写解析jstat输出的脚本,可能需要针对此工具的未来版本修改这些脚本。
-statOption
确定jstat显示的统计信息。下表列出了可用的选项。使用常规选项-options可以显示特定平台安装的选项列表。
选项 |
显示... |
类加载器的行为统计 |
|
HotSpot即时编译器的行为统计 |
|
堆的垃圾回收器的行为统计 |
|
Java各代区域以及对应空间的容量统计 |
|
垃圾回收的摘要信息(等同于-gcutil), 以及最后的和当前的(如适用)垃圾回收事件的原因。 |
|
new generation的行为统计 |
|
new generation及其对应空间的大小统计。 |
|
old和permanent generation的行为统计。 |
|
old generation的大小统计。 |
|
permanent generation的大小统计。 |
|
垃圾回收统计的摘要信息。 |
|
HotSpot汇编方法统计。 |
-h n
每过n个样例(输出行)就显示一个列头,n为一个正整数。默认值为0,即只在数据的第一行上面显示列头。
-t n
显示时间戳列,并作为输出的第一个列。该时间戳表示目标JVM启动时间到当前时间的间隔时间。
-JjavaOption
传递javaOption到java应用启动程序。例如:-J-Xms48m设置启动内存为48MB。想要了解完整的选项列表,请参考下列文档:
· java - the Java application launcher (Solaris)
· java - the Java application launcher (Linux)
· java - the Java application launcher (Windows)
STATOPTIONS和输出
下列表格概括了jstat为每个statOption输出的列。
-class选项
类加载器的统计信息
列 |
描述 |
Loaded |
加载的类的数量 |
Bytes |
加载的Kbyte数 |
Unloaded |
已卸载的类的数量 |
Bytes |
已卸载的Kbyte数 |
Time |
执行类的加载和卸载操作所耗费的时间 |
-compiler选项
HotSpot即时(Just-In-Time)编译器的统计信息
列 |
描述 |
Compiled |
已执行的编译任务数 |
Failed |
失败的编译任务数 |
Invalid |
无效的编译任务数 |
Time |
执行编译任务所耗费的时间 |
FailedType |
最后失败的编译的编译类型 |
FailedMethod |
最后失败的编译的类名和方法 |
-gc选项
垃圾回收堆的统计信息
列 |
描述 |
S0C |
survivor space 0的当前容量(KB). |
S1C |
survivor space 1的当前容量(KB). |
S0U |
survivor space 0使用的容量(KB). |
S1U |
survivor space 1使用的容量(KB). |
EC |
Eden space的当前容量(KB). |
EU |
Edenspace的已用容量(KB). |
OC |
Oldspace的当前容量(KB). |
OU |
Old space的已用容量(KB). |
PC |
Permanent space的当前容量(KB). |
PU |
Permanentspace的已用容量(KB). |
YGC |
Younggeneration的GC事件数量 |
YGCT |
Younggeneration的垃圾回收事件 |
FGC |
Full GC事件的数量 |
FGCT |
Full GC的时间 |
GCT |
总计的垃圾回收时间 |
-gccapacity选项
内存池的分代和空间容量Memory Pool Generation and Space Capacities
Column |
Description |
NGCMN |
newgeneration的最小容量(KB). |
NGCMX |
newgeneration的最大容量(KB). |
NGC |
newgeneration的当前容量(KB). |
S0C |
survivor space 0的当前容量(KB). |
S1C |
survivor space 1的当前容量(KB). |
EC |
Eden space的当前容量(KB). |
OGCMN |
Old generation的最小容量(KB). |
OGCMX |
Oldgeneration的最大容量(KB). |
OGC |
Oldgeneration的当前容量(KB). |
OC |
Old space的当前容量(KB). |
PGCMN |
Permanentgeneration的最小容量(KB). |
PGCMX |
Permanentgeneration的最大容量(KB). |
PGC |
Permanentgeneration的当前容量(KB). |
PC |
Permanent space的当前容量(KB). |
YGC |
Younggeneration的GC事件数 |
FGC |
Full GC事件的数量 |
-gccause选项
此选项显示与-gcutil选项相同的垃圾回收统计摘要信息,但却包括最后的和当前的(如适用)垃圾回收事件的原因。除了-gcutil列出的列,此选项还添加了以下列:
垃圾回收统计,包括GC事件
列 |
描述 |
LGCC |
最后的垃圾回收的原因 |
GCC |
当前的垃圾回收的原因 |
-gcnew选项
新生代(New)的统计信息
列 |
描述 |
S0C |
survivor space 0的当前容量(KB). |
S1C |
survivor space 1的当前容量(KB). |
S0U |
survivor space 0的已用容量(KB). |
S1U |
survivor space 1的已用容量(KB). |
TT |
期限阈值 |
MTT |
最大的期限阈值 |
DSS |
所需的幸存者(survivor)大小(KB). |
EC |
Eden space的当前容量(KB). |
EU |
Eden space的已用容量(KB). |
YGC |
Young generation的GC事件数 |
YGCT |
Young generation的垃圾回收时间 |
-gcnewcapacity选项
新生代(new)的空间大小统计
列 |
描述 |
NGCMN |
new generation的最小容量(KB). |
NGCMX |
new generation的最大容量(KB). |
NGC |
new generation的当前容量(KB). |
S0CMX |
survivor space 0的最大容量(KB). |
S0C |
survivor space 0的当前容量(KB). |
S1CMX |
survivor space 1的最大容量(KB). |
S1C |
survivor space 1的当前容量(KB). |
ECMX |
Eden space的最小容量(KB). |
EC |
Eden space的当前容量(KB). |
YGC |
Young generation的GC事件数 |
FGC |
Full GC事件的数量 |
-gcold选项
Old和Permanent Generation的统计信息
列 |
描述 |
PC |
permanent space的当前容量(KB). |
PU |
Permanent space的已用容量(KB). |
OC |
old space的当前容量(KB). |
OU |
old space的已用容量(KB). |
YGC |
young generation的GC事件数 |
FGC |
Full GC事件的数量 |
FGCT |
Full GC的时间 |
GCT |
总计的垃圾回收时间 |
-gcoldcapacity选项
Old Generation的统计信息
列 |
描述 |
OGCMN |
old generation的最小容量(KB). |
OGCMX |
old generation的最大容量(KB). |
OGC |
old generation的当前容量(KB). |
OC |
old space的当前容量(KB). |
YGC |
young generation的GC事件数 |
FGC |
Full GC事件的数量 |
FGCT |
Full GC的时间 |
GCT |
总计的垃圾回收时间 |
-gcpermcapacity选项
Permanent Generation的统计信息
列 |
描述 |
PGCMN |
permanent generation的最小容量(KB). |
PGCMX |
permanent generation的最大容量(KB). |
PGC |
permanent generation的当前容量(KB). |
PC |
permanent space的当前容量(KB). |
YGC |
young generation的GC事件数 |
FGC |
Full GC 事件的数量 |
FGCT |
Full GC的时间 |
GCT |
总计的垃圾回收时间 |
-gcutil选项
垃圾回收统计的摘要信息
列 |
描述 |
S0 |
Survivor space 0已用容量占当前容量的百分比 |
S1 |
Survivor space 1已用容量占当前容量的百分比 |
E |
Eden space已用容量占当前容量的百分比 |
O |
Old space已用容量占当前容量的百分比 |
P |
Permanent space已用容量占当前容量的百分比 |
YGC |
young generation的GC事件数 |
YGCT |
Young generation的垃圾回收时间 |
FGC |
Full GC 事件的数量 |
FGCT |
Full GC的时间 |
GCT |
总计的垃圾回收时间 |
-printcompilation选项
HotSpot编译器方法统计
列 |
描述 |
Compiled |
已执行的编译任务数 |
Size |
方法字节码的字节数 |
Type |
编译类型 |
Method |
表示被编译方法的类名和方法名。类名使用"/"替代"."作为命名空间的分隔符。方法名是给定的类的方法。这两个字段的格式与HotSpot选项- XX:+PrintComplation是一致的。 |
示例
本节介绍监控lvmid为21891的本地JVM的几个示例。
使用gcutil选项
本示例附于lvmid 21891,每过250毫秒获取7个样本,并指定-gcutil选项来显示输出。
jstat -gcutil 21891 250 7
S0 S1 E O P YGC YGCT FGC FGCT GCT
12.44 0.00 27.20 9.49 96.70 78 0.176 5 0.495 0.672
12.44 0.00 62.16 9.49 96.70 78 0.176 5 0.495 0.672
12.44 0.00 83.97 9.49 96.70 78 0.176 5 0.495 0.672
0.00 7.74 0.00 9.51 96.70 79 0.177 5 0.495 0.673
0.00 7.74 23.37 9.51 96.70 79 0.177 5 0.495 0.673
0.00 7.74 43.82 9.51 96.70 79 0.177 5 0.495 0.673
0.00 7.74 58.11 9.51 96.71 79 0.177 5 0.495 0.673
该示例的输出表明,第3和第4个样本之间发生了一个young generation的垃圾回收。此次回收耗费0.001秒,并将eden space(E)的对象推进到old space(O),结果使得old space的已用容量从9.49%增加到9.51%。在回收之前,survivor space使用了12.44%,但在回收之后,仅使用了7.74%。
重复列的标题字符串
本示例附于lvmid 21891,每过250毫秒获取一次样本,并指定-gcutil选项来显示输出。此外,它使用-h3选项来实现每显示3行数据之后输出一次列标题。
jstat -gcnew -h3 21891 250
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
64.0 64.0 0.0 31.7 31 31 32.0 512.0 178.6 249 0.203
64.0 64.0 0.0 31.7 31 31 32.0 512.0 355.5 249 0.203
64.0 64.0 35.4 0.0 2 31 32.0 512.0 21.9 250 0.204
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
64.0 64.0 35.4 0.0 2 31 32.0 512.0 245.9 250 0.204
64.0 64.0 35.4 0.0 2 31 32.0 512.0 421.1 250 0.204
64.0 64.0 0.0 19.0 31 31 32.0 512.0 84.4 251 0.204
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
64.0 64.0 0.0 19.0 31 31 32.0 512.0 306.7 251 0.204
除了显示重复的标题字符串,此示例还显示,在第2和第3个样本之间,发生了一次young GC。它耗费了0.001秒。此次回收发现了足够多的活跃数据,survivor space 0的使用空间(S0U)已经超过所需的survivor大小(DSS)。结果,对象被推进old generation(本次输出中不可见),期限阈值(TT)从31降到2。
第5和第6个样本之间发生了另一次垃圾回收。此次回收只发现了少许的survivor,期限阈值又返回到了31。
每个样本包含一个时间戳
本示例附于lvmid 21891,并且每过250毫秒就提取3个样本。选项-t用来为每个样本在第一列生成一个时间戳。
jstat -gcoldcapacity -t 21891 250 3
Timestamp OGCMN OGCMX OGC OC YGC FGC FGCT GCT
150.1 1408.0 60544.0 11696.0 11696.0 194 80 2.874 3.799
150.4 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863
150.7 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863
Timestamp列报告了自目标虚拟机启动以后所消逝的时间,单位是秒。此外, 选项-gcoldcapacity显示,为了满足分配或提升的需求,old generation的容量(OGC)和old space的容量(OC)随着堆的扩张而增加。在第81次Full GC(FGC)之后,old generation的容量(OGC)从11696KB增长到13820KB。generation(和space)的最大容量为60544KB(OGCMX),因此它仍然有扩张的空间。
监控远程JVM
本示例附于名为remote.domain的系统的lvmid 40496,使用-gcutil选项,并且无限期地每秒获取一次样本。
jstat -gcutil 40496@remote.domain 1000
...省略输出
lvmid与远程主机的名称结合,构成了一个lvmid -- 40496@remote.domain。该vmid导致使用rmi协议来与远程主机的默认jstatd服务器进行通讯。jstatd服务器位于remote.domain之上,并使用绑定默认rmiregistry端口号(1099)的rmiregistry。
Jstatd
jstatd,即虚拟机的jstat守护进程,主要用于监控JVM的创建与终止,并提供一个接口允许远程监控工具依附到在本地主机上运行的JVM。
用法摘要
jstatd [ options ]
命令行选项。这些选项可以是任意顺序。如果存在多余的或者自相矛盾的选项,则优先考虑最后的选项。
描述
jstatd工具是一个RMI服务器应用程序,主要用于监控HotSpot Java 虚拟机的创建与终止,并提供一个接口以允许远程监控工具附加到本地主机上运行的JVM上。
jstatd服务器需要在本地主机上存在一个RMI注册表。jstatd服务器将尝试在默认端口或-p port选项指定的端口附加到该RMI注册表上。如果RMI注册表不存在,jstatd应用程序将会自动创建一个,并绑定到-p port选项指定的端口上,如果省略了-p port选项,则绑定到默认的RMI注册表端口。你可以通过指定-nr选项来抑制内部RMI注册表的创建。
注意:此工具是不受支持的,并且无法确定在未来版本的JDK中是否可用。目前,此工具不适用于Windows 98和Windows ME平台。
选项
jstatd命令支持以下选项:
-nr
当找不到现有的RMI注册表时,不尝试使用jstatd进程创建一个内部的RMI注册表。
-p port
在指定的端口查找RMI注册表。如果没有找到,并且没有指定-nr选项,则在该端口自行创建一个内部的RMI注册表。
-n rminame
RMI注册表中绑定的RMI远程对象的名称。默认的名称为JStatRemoteHost。如果多个jstatd服务器在同一主机上运行,你可以通过指定该选项来让每个服务器导出的RMI对象具有唯一的名称。不管如何,这样做需要将唯一的服务器名称包含进监控客户端的hostid和vmid字符串中。
-Joption
将选项参数传递给被javac调用的java启动程序。例如,-J-Xms48m设置启动内存为48 MB。使用-J将选项参数传递给执行Java应用程序的底层虚拟机,这是一种常见惯例。
安全性
jstatd只能够监控具有适当的本地访问权限的JVM。因此,jstatd进程必须以与目标JVM相同的用户凭证来运行。某些用户凭据,例如基于Unix系统的root用户,有权限访问系统中任何JVM导出的instrumentation。以此凭据运行的jstatd进程可以监控系统上的任何JVM,但会引入一些额外的安全隐患。
jstatd服务器不提供远程客户端的任何授权许可。因此,通过那些jstatd进程有权访问网络中任何用户的所有JVM,运行jstatd进程会暴露instrumentation出口。这种接触可能不是你的当前环境所想要的;在启动jstatd进程之前,尤其是和生产环境或者非安全的网络中,你应该考虑本地的安全策略。
如果没有安装其他的安全管理器,jstatd服务器会安装一个RMISecurityPolicy的实例,因此需要指定一个安全策略文件。策略文件必须遵循该默认策略实现的策略文件语法。
下列策略文件将允许jstatd服务器在没有任何安全例外的情况下运行。该策略没有授权所有权限给所有代码库那么自由,但却比授予最小的权限来运行jstatd服务器更自由。
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
为了使用此策略,请复制上述文本到一个名叫jstatd.all.policy的文件中,并使用如下命令运行jstatd服务器:
jstatd -J-Djava.security.policy=jstatd.all.policy
对于具有更严格的安全实践的网络场所而言,可能使用一个自定义的策略文件来显示对特定的可信主机或网络的访问,尽管这种技术容易受到IP地址欺诈攻击。 如果你的安全问题无法使用一个定制的策略文件来处理,那么最安全的操作是不运行jstatd服务器,而是在本地使用jstat和jps工具。
远程接口
jstatd进程输出的接口是私有的,并会产生变化。不鼓励用户和开发者往此接口写入数据。
示例
这里有一些启动jstatd的示例。注意,jstatd脚本会自动在后台启动服务器。
使用内部的RMI注册表
本示例演示启动jstatd,并使用内部RMI注册表。本示例假定没有其它服务器绑定到默认的RMI注册表端口(端口号 1099)。
jstatd -J-Djava.security.policy=all.policy
使用外部的RMI注册表
本示例演示启动jstatd,并使用外部RMI注册表。
rmiregistry&
jstatd -J-Djava.security.policy=all.policy
本示例演示启动jstatd,并使用端口2020上的外部RMI注册表。
rmiregistry 2020&
jstatd -J-Djava.security.policy=all.policy -p 2020
本示例演示启动jstatd,并使用端口2020上的外部RMI注册表,绑定的RMI远程对象名称为AlternateJstatdServerName。
rmiregistry 2020&
jstatd -J-Djava.security.policy=all.policy -p 2020 -n AlternateJstatdServerName
抑制进程中的RMI注册表的创建
本示例演示启动jstatd,而且即使找不到现有的RMI注册表,也不会创建一个新的RMI注册表。本示例假定已经有一个RMI注册表在运行中。如果没有,则发出适当的错误信息。
jstatd -J-Djava.security.policy=all.policy -nr
启动RMI日志能力
本示例演示启动jstatd,并启用RMI日志功能。该技术对于故障排除的援助或者监控服务器活动非常有用。
jstatd -J-Djava.security.policy=all.policy -J-Djava.rmi.server.logCalls=true
另请参阅
Jvisualvm
jvisualvm,即Java VisualVM,是一个图形化界面的Java虚拟机监控工具。jvisualvm主要提供在Java虚拟机上运行的Java应用程序的详细信息。
使用jvisualvm,你可以详细查看虚拟机中每个Java应用程序,甚至每个线程、每个类、每个实例的相关信息,包括堆栈、字段、类型、方法值,以及启动时间、方法调用次数等。
你可以暂时先参考以下网址:http://visualvm.java.net/zh_CN/gettingstarted.html
最后
交流群:244930845