JDK中除了包含与开发密切相关的jar包外,还包含了很多非常实用的工具。在%JAVA_HOME%in目录下面除了命令行工具外,还包括了几个强大的可视化工具。这些工具可以辅助我们开发、调试应用程序以及监控虚拟机状态,因此尤其是对于开发人员而言,熟练掌握这些工具非常有必要。随JDK1.8一起发布的工具如下:
本文中将使用jconsole和jvisualvm来监控虚拟机状态。
一 javac,java,jar三个命令的用法
1.javac命令的用法
C:Usersmichael>javac 用法: javac <options> <source files> 其中, 可能的选项包括: -g 生成所有调试信息 -g:none 不生成任何调试信息 -g:{lines,vars,source} 只生成某些调试信息 -nowarn 不生成任何警告 -verbose 输出有关编译器正在执行的操作的消息 -deprecation 输出使用已过时的 API 的源位置 -classpath <路径> 指定查找用户类文件和注释处理程序的位置 -cp <路径> 指定查找用户类文件和注释处理程序的位置 -sourcepath <路径> 指定查找输入源文件的位置 -bootclasspath <路径> 覆盖引导类文件的位置 -extdirs <目录> 覆盖所安装扩展的位置 -endorseddirs <目录> 覆盖签名的标准路径的位置 -proc:{none,only} 控制是否执行注释处理和/或编译。 -processor <class1>[,<class2>,<class3>...] 要运行的注释处理程序的名称; 绕过默认的搜索进程 -processorpath <路径> 指定查找注释处理程序的位置 -d <目录> 指定放置生成的类文件的位置 -s <目录> 指定放置生成的源文件的位置 -implicit:{none,class} 指定是否为隐式引用文件生成类文件 -encoding <编码> 指定源文件使用的字符编码 -source <发行版> 提供与指定发行版的源兼容性 -target <发行版> 生成特定 VM 版本的类文件 -version 版本信息 -help 输出标准选项的提要 -A关键字[=值] 传递给注释处理程序的选项 -X 输出非标准选项的提要 -J<标记> 直接将 <标记> 传递给运行时系统 -Werror 出现警告时终止编译 @<文件名> 从文件读取选项和文件名
C:Usersmichael>javac -X
输出非标准选项的提要:这个选项在不同的平台下面输出结果略微不同。此处省略输出。
2.java命令的用法
C:Usersmichael>java 用法: java [-options] class [args...] (执行类) 或 java [-options] -jar jarfile [args...] (执行 jar 文件) 其中选项包括: -d32 使用 32 位数据模型 (如果可用) -d64 使用 64 位数据模型 (如果可用) -server 选择 "server" VM 默认 VM 是 server. -cp <目录和 zip/jar 文件的类搜索路径> -classpath <目录和 zip/jar 文件的类搜索路径> 用 ; 分隔的目录, JAR 档案和 ZIP 档案列表, 用于搜索类文件。 -D<名称>=<值> 设置系统属性 -verbose:[class|gc|jni] 启用详细输出 -version 输出产品版本并退出 -version:<值> 需要指定的版本才能运行 -showversion 输出产品版本并继续 -jre-restrict-search | -no-jre-restrict-search 在版本搜索中包括/排除用户专用 JRE -? -help 输出此帮助消息 -X 输出非标准选项的帮助 -ea[:<packagename>...|:<classname>] -enableassertions[:<packagename>...|:<classname>] 按指定的粒度启用断言 -da[:<packagename>...|:<classname>] -disableassertions[:<packagename>...|:<classname>] 禁用具有指定粒度的断言 -esa | -enablesystemassertions 启用系统断言 -dsa | -disablesystemassertions 禁用系统断言 -agentlib:<libname>[=<选项>] 加载本机代理库 <libname>, 例如 -agentlib:hprof 另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help -agentpath:<pathname>[=<选项>] 按完整路径名加载本机代理库 -javaagent:<jarpath>[=<选项>] 加载 Java 编程语言代理, 请参阅 java.lang.instrument -splash:<imagepath> 使用指定的图像显示启动屏幕有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation/index.html。 C:Usersmichael>java -X -Xmixed 混合模式执行 (默认) -Xint 仅解释模式执行 -Xbootclasspath:<用 ; 分隔的目录和 zip/jar 文件> 设置搜索路径以引导类和资源 -Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件> 附加在引导类路径末尾 -Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件> 置于引导类路径之前 -Xdiag 显示附加诊断消息 -Xnoclassgc 禁用类垃圾收集 -Xincgc 启用增量垃圾收集 -Xloggc:<file> 将 GC 状态记录在文件中 (带时间戳) -Xbatch 禁用后台编译 -Xms<size> 设置初始 Java 堆大小 -Xmx<size> 设置最大 Java 堆大小 -Xss<size> 设置 Java 线程堆栈大小 -Xprof 输出 cpu 配置文件数据 -Xfuture 启用最严格的检查, 预期将来的默认值 -Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档) -Xcheck:jni 对 JNI 函数执行其他检查 -Xshare:off 不尝试使用共享类数据 -Xshare:auto 在可能的情况下使用共享类数据 (默认) -Xshare:on 要求使用共享类数据, 否则将失败。 -XshowSettings 显示所有设置并继续 -XshowSettings:all 显示所有设置并继续 -XshowSettings:vm 显示所有与 vm 相关的设置并继续 -XshowSettings:properties 显示所有属性设置并继续 -XshowSettings:locale 显示所有与区域设置相关的设置并继续 -X 选项是非标准选项, 如有更改, 恕不另行通知。
3.jar命令的用法
C:Usersmichael>jar 用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ... 选项包括: -c 创建新的归档文件 -t 列出归档目录 -x 从档案中提取指定的 (或所有) 文件 -u 更新现有的归档文件 -v 在标准输出中生成详细输出 -f 指定归档文件名 -m 包含指定清单文件中的清单信息 -e 为捆绑到可执行 jar 文件的独立应用程序 指定应用程序入口点 -0 仅存储; 不使用情况任何 ZIP 压缩 -M 不创建条目的清单文件 -i 为指定的 jar 文件生成索引信息 -C 更改为指定的目录并包含其中的文件 如果有任何目录文件, 则对其进行递归处理。清单文件名, 归档文件名和入口点名称的指定顺序与 'm', 'f' 和 'e' 标记的指定顺序相同。 示例 1: 将两个类文件归档到一个名为 classes.jar 的归档文件中: jar cvf classes.jar Foo.class Bar.class 示例 2: 使用现有的清单文件 'mymanifest' 并 将 foo/ 目录中的所有文件归档到 'classes.jar' 中: jar cvfm classes.jar mymanifest -C foo/ . C:Usersmichael>jar cvf tp.jar TimePrinter.class 【注:没有指定应用程序入口,所以该jar包无法执行】 已添加清单 正在添加: TimePrinter.class(输入 = 620) (输出 = 433)(压缩了 30%) C:Usersmichael>java -jar tp.jar tp.jar中没有主清单属性 C:Usersmichael>jar cvfe tp.jar TimePrinter TimePrinter.class 【注:选项cvfe中添加了e,TimePrinter为主类】 已添加清单 正在添加: TimePrinter.class(输入 = 620) (输出 = 433)(压缩了 30%) C:Usersmichael>java -jar tp.jar Fri Apr 10 09:42:43 CST 2015 Fri Apr 10 09:42:44 CST 2015
二 编译并运行测试程序
该测试程序的功能是每隔一秒向控制台输出当前时间,TimePrinter.java 源码如下:
public class TimePrinter { public static void main(String[] args) throws Exception{ for(int i = 0;i< 1000;i++){ System.out.println(new java.util.Date()); Thread.sleep(1000); } } }
1. 编译源文件
C:Usersmichael>javac -verbose TimePrinter.java [解析开始时间 RegularFileObject[TimePrinter.java]] [解析已完成, 用时 47 毫秒] [源文件的搜索路径: .] [类文件的搜索路径: C:Program FilesJavajdk1.7.0_51jrelib esources.jar,C:Program Files... [正在加载ZipFileIndexFileObject[C:Program FilesJavajdk1.7.0_51libct.sym(META-INF/sym/rt.jar/java/lang/String.class)]]
... [正在检查TimePrinter] [正在加载ZipFileIndexFileObject[C:Program FilesJavajdk1.7.0_51libct.sym(META-INF/sym/rt.jar/java/lang/AutoCloseable.class)]] ... [已写入RegularFileObject[TimePrinter.class]] [共 920 毫秒]
2.设置VM参数并运行程序
(1)class方式运行
C:Usersmichael>java -Xms20m -Xmx20m -Xmn10m TimePrinter
Fri Apr 10 09:42:43 CST 2015
Fri Apr 10 09:42:44 CST 2015
(2)jar方式运行
C:Usersmichael>java -Xms20m -Xmx20m -Xmn10m -jar tp.jar Fri Apr 10 09:42:43 CST 2015 Fri Apr 10 09:42:44 CST 2015
注:Eclipse下选择Run->Run Configurations设置VM运行参数,如下图:
当然还可以设置更多的参数,比如:
C:Usersmichael>java -Xms200M -Xmx200M -Xmn100M -Xss100M -XX:PermSize=100M -XX:MaxPermSize=100M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 TimePrinter
注意:有的选项带值:-XX:SurvivorRatio=8 ;有的是带加减号,比如-XX:+PrintGCDetails .(带加减号的话,估计就是true或false的意思)
三 用jconsole监控运行状态
1.我们计划将堆的总太小设为20M,新生代和老年代各10M。由于默认情况下survivor和eden的空间比例是1:8,所以Eden大约8M,2个survivor各自1M。下面验证一下jconsole的监控情况和我们的计划是否一致。
(1)堆的总大小:
(2)老年代大小:
(3)Eden大小:
(4)survivor大小:
结果:符合预期计划。
2.其他信息
3.缺点:jconsole会对被监控程序的正常运行产生影响。
就本测试程序而言,当运行jconsole程序监控TimePrinter程序时,会发现TimePrinter会输出一些额外的类加载信息,从侧面说明了TimePrinter会额外加载部分类以支持jconsole的工作。
四 用jvisualvm监控运行状态
和jconsole相比,jvisualvm的线程可视化做得很好。而且jvisualvm还有一个很大的优点:不需要被监视的程序基于特殊Agent运行,因此它对于应用程序的实际性能影响很小。jvisualvm是Oracle力推的工具,以后主要就用它了。