快捷搜索:

关于 JVM 命令行标志您不知道的 5 件事:调优 J

VM 是多半开拓职员视为天经地义的 Java 功能和机能背后的重负荷机械。然而,我们很少有人能理解 JVM 是若何进行事情的 — 像义务分配和垃圾网络、迁移转变线程、打开和关闭文件、中断和/或 JIT 编译 Java 字节码,等等。

不认识 JVM 将不仅会影响利用法度榜样机能,而且当 JVM 出问题时,考试测验修复也会很艰苦。

本期 5 件事 系列 将先容一些敕令行标志,您可以应用它们来诊断和调优您的 Java 虚拟机机能。

1. DisableExplicitGC

我已记不清有若干次用户要求我就利用法度榜样机能问题供给咨询了,着实只要跨代码快速运行 grep,就会发明清单 1 所示的问题 — 原始 java 机能反模式:

清单 1. System.gc();

// We just released a bunch of objects, so tell the stupid

// garbage collector to collect them already!

System.gc();

显式垃圾网络是一个异常糟糕的主见 — 就像将您和一个猖狂的斗牛犬锁在一个电话亭里。只管调用的语法是依附实现的,但假如您的 JVM 正在运行一个分代的垃圾收受接收器(大年夜多半是)System.gc(); 逼迫 VM 履行一个堆的 “整个清扫”,虽然有的没有需要。整个清扫比一个老例 GC 操作要昂贵好几个数量级,这只是个简单数学问题。

您可以不把我的话放在心上 — Sun 的工程师为这个特殊的人工差错供给一个 JVM 标志; -XX:+DisableExplicitGC 标志自动将 System.gc() 调用转换成一个空操作,为您供给运行代码的时机,您自己看看 System.gc() 对付全部 JVM 履行有害照样有利。

2. HeapDumpOnOutOfMemoryError

您有没有经历过这样的环境:JVM 不能应用,赓续抛出 OutOfMemoryError,而您又不能为自己创建调试器来捕获它或查看呈现了什么问题?像这类偶发和/或不确定的问题,平日使开拓职员发疯。

买者自傲

并不是任何 VM 都支持所有敕令行标志,Sun/Oracle 的 VM 除外。查明一个标志是否被支持的最好措施是试用它,看它是否正常事情。假使这些标志在技巧上是不支持的,那么,应用它们您要承担整个责任。假如这些标志中的任何一个使您的代码、您的数据、您的办事器或您的统统消掉得无影无踪,我、Sun/Oracle 和 IBM® 都将不认真任。为以防万一,建议先在虚拟(异常临盆)情况中实验。

在这个时候您想要的是,在 JVM 殒命之际捕获堆的一个快照 — 恰恰 -XX:+HeapDumpOnOutOfMemoryError 敕令可以完成这一操作。

运行该敕令看护 JVM 拍摄一个 “堆转储快照”,并将其保存在一个文件中以便处置惩罚,平日应用 jhat 实用对象(我在 上一篇文章 中先容过)。您可以应用响应的 -XX:HeapDumpPath 标志指定到保存文件的实际路径。(不管文件保存在哪,务必确保文件系统和/或 Java 流程必须要有权限设置设置设备摆设摆设,可以在此中写入。)

3. bootclasspath

按期将一个类放入类路径是很有赞助的,这类路径与库存 JRE 附带的类路径或者以某种要领扩展的 JRE 类路径略有不合。(新 Java Crypto API 供给商便是一个例子)。假如您想要扩展 JRE ,那么您定制的实现必须可以应用向导法度榜样 ClassLoader,该向导法度榜样可以加载 rt.jar 中的 java.lang.Object 及其所有相关文件。

只管您可以 不法打开 rt.jar 并将您的定制实现或新数据包移入此中,但从技巧上您就违反了您下载 JDK 时批准的协议了。

相反,应用 JVM 自己的 -Xbootclasspath 选项,以及皮肤 -Xbootclasspath/p 和 -Xbootclasspath/a。

-Xbootclasspath 使您可以设置完备的向导类路径(这平日包括一个对 rt.jar 的引用),以及一些其他 JDK 附带的(不是 rt.jar 的一部分)JAR 文件。-Xbootclasspath/p 将值前置到现有 bootclasspath 中,并将 -Xbootclasspath/a 附加到此中。

例如,假如您改动了库中的 java.lang.Integer,并将改动放在一个子路径 mods 下,那么 -Xbootclasspath/a mods 参数将新 Integer 放在默认的参数前面。

4. verbose

对付虚拟的或任何类型的 Java 利用法度榜样,-verbose 是一个很有用的一级诊断应用法度榜样。该标志有三个子标志:gc、class 和 jni。

开拓职员考试测验探求是否 JVM 垃圾网络器发生故障或者导致机能低下,平日首先要做的便是履行 gc。不幸的是,解释 gc 输出很麻烦 — 足够写一本书。更糟糕的是,在敕令行中打印的输出在不合的 Java 版本中或者不在不合的 JVM 中会发生改变,这使得精确解释变得更难。

一样平常来说,假如垃圾网络器是一个分代网络器(多半 “企业级” VMs 都是)。某种虚拟标志将会呈现,来指出一个整个清扫 GC 通路;在 Sun JVM 中,标志在 GC 输出行的开始以 “[Full GC ...]” 形式呈现。

想要诊断 ClassLoader 和/或不匹配的类冲突,class 可以帮上大年夜忙。它不仅申报类何时加载,还申报类从何处加载,包括到 JAR 的路径(假如来自 JAR)。

jni 很少应用,除了应用 JNI 或本地库时。打开时,它将申报各类 JNI 事故,比如,本地库何时加载,措施何时弹回;再一次强调,在不合 JVM 版本中,输出会发生变更。

5. Command-line -X

我列出了 JVM 中供给的我爱好的敕令行选项,然则还有一些更多的必要您自己发明,运行敕令行参数 -X,列出 JVM 供给的所有非标准(但大年夜部分都是安然的)参数 — 例如:

-Xint,在解释模式下运行 JVM(对付测试 JIT 编译器实际上是否对您的代码起感化或者验证是否 JIT 编译器中有一个 bug,这都很有用)。

-Xloggc:,和 -verbose:gc 做同样的事,然则记录一个文件而不输出到敕令行窗口。

JVM 敕令行选项时常发生变更,是以,按期查看是一个好主见。以致,您深夜盯着监控器和下昼 5 点回家和妻子孩子吃顿晚饭,(或者在 Mass Effect 2 中祛除您的对头,根据您的喜爱),它们都是不一样的。

停止语

在临盆情况中,敕令行标志不是为永远应用而设计的 — 事实上,除了您终止用来调优 JVM 垃圾网络器的标志,没有一个非标准敕令行标记是专用于临盆应用的。然则,作为对象来密查在其他方面完全不透明的虚拟机的内部事情,是异常有用的。

您可能还会对下面的文章感兴趣: