当前位置: 首页 > 科技观察

每个Java程序员都必须知道的5个JVM命令行标志

时间:2023-03-22 17:16:43 科技观察

不熟悉JVM不仅会影响应用程序性能,而且当JVM出现故障时,修复它可能会很困难。本文介绍了一些可用于诊断和调整Java虚拟机性能的命令行标志。1.DisableExplicitGC我已经记不清有多少次用户找我咨询应用程序性能问题了,其实只要快速grep一下代码,就会发现清单1所示的问题——原来的Java性能问题反模式:清单1.System.gc;//我们刚刚释放了一堆对象,所以告诉愚蠢的//垃圾收集器已经收集它们了!系统.gc;斗牛犬锁在电话亭里。虽然调用的语法依赖于实现,但如果您的JVM正在运行分代垃圾收集器(主要是System.gc);强制VM执行堆的“完全扫描”,尽管有些不是必需的。完全扫描比常规GC操作要昂贵几个数量级,这只是一个简单的数学问题。你可以相信我的话——Sun的工程师为这个特定的人为错误提供了一个JVM标志;-XX:+DisableExplicitGC标志会自动将System.gc调用变为空操作,让您有机会运行代码,亲自查看System.gc对整体JVM执行是有害还是有益。2.HeapDumpOnOutOfMemoryError你是否遇到过JVM不可用,不断抛出OutOfMemoryError,而你无法自己创建一个调试器来捕获它或查看哪里出了问题的情况?像这样的问题是零星的和/或不确定的,通常会让开发人员抓狂。并非所有命令行标志都受任何VM支持,Sun/OracleVM除外,由买方自行决定。查明是否支持标志的最佳方法是尝试一下,看看它是否有效。如果此类标志在技术上不受支持,则使用它们的风险完全由您自行承担。如果这些标志中的任何一个使您的代码、您的数据、您的服务器或您的一切消失得无影无踪,我、Sun/Oracle或IBM均不承担任何责任。为了以防万一,建议先在虚拟(非常生产)环境中进行试验。此时您想要的是在JVM死机时捕获堆的快照——这正是-XX:+HeapDumpOnOutOfMemoryError命令所做的。运行此命令告诉JVM获取“堆转储快照”并将其保存在文件中以供处理,通常使用jhat实用程序(在我之前的帖子中介绍)。您可以使用相应的-XX:HeapDumpPath标志指定保存文件的实际路径。(无论文件保存在哪里,都要确保文件系统和/或Java进程必须有权限配置,并且可以写入。)3.bootclasspath周期性的把一个class放到classpath中是有帮助的,是一样的作为标准JRE或以某种方式扩展的JRE附带的类路径略有不同。(新的JavaCryptoAPI提供程序就是一个例子)。如果您想扩展JRE,您的自定义实现必须能够访问引导类加载器,它可以加载java.lang.Object及其在rt.jar中的所有相关文件。虽然您可以非法打开rt.jar并将您的自定义实现或新包移入其中,但从技术上讲,您违反了下载JDK时同意的协议。相反,使用JVM自己的-Xbootclasspath选项,以及皮肤-Xbootclasspath/p和-Xbootclasspath/a。-Xbootclasspath允许您设置完整的引导类路径(这通常包括对rt.jar的引用)以及JDK附带的一些其他JAR文件(不是rt.jar的一部分)。-Xbootclasspath/p将值添加到现有的bootclasspath并将-Xbootclasspath/a附加到它。例如,如果你修改了库中的java.lang.Integer,并将修改放在一个子路径mods下,那么-Xbootclasspath/amods参数会将新的Integer放在默认参数的前面。4.verbose对于虚拟或任何类型的Java应用程序,-verbose是一个有用的一级诊断实用程序。该标志具有三个子标志:gc、class和jni。当开发人员试图查明JVM垃圾收集器是否出现故障或导致性能不佳时,通常要做的第一件事就是执行gc。不幸的是,解释gc输出很麻烦——足以写一本书。更糟糕的是,打印在命令行上的输出可能会在不同的Java版本中发生变化,或者在不同的JVM中不会发生变化,这使得正确解释变得更加困难。一般来说,如果垃圾收集器是分代收集器(大多数“企业”VM都是)。将出现某种虚拟标志以指示完全扫描GC通过;在SunJVM中,标志在GC输出行的开头显示为“[FullGC...]”。在诊断ClassLoader和/或不匹配的类冲突时,class可以提供很大的帮助。它不仅报告加载类的时间,还报告加载类的位置,如果它来自JAR,则包括JAR的路径。jni很少使用,除非使用JNI或本机库。开启后,它会报告各种JNI事件,例如加载本机库时,跳出方法时;同样,输出会因JVM版本而异。5.Command-line-X我列出了JVM提供的我喜欢的命令行选项,还有一些需要你自己去发现,运行命令行参数-X,列出所有非标准的(但它们中的大多数是安全的)参数-例如:-Xint,以解释模式运行JVM(非常适合测试JIT编译器是否真的在您的代码上工作或验证它工作的JIT编译器中是否存在错误)。-Xloggc:做与-verbose:gc相同的事情,但记录到文件而不是输出到命令窗口。JVM命令行选项会不时更改,因此最好定期检查它们。深夜盯着显示器和下午5点回家与妻子和孩子共进晚餐(或在质量效应2中杀死敌人,这取决于您的偏好)之间甚至存在差异。结论命令行标志不是为在生产环境中永久使用而设计的——事实上,除了您终止以调整JVM垃圾收集器的那个之外,没有一个非标准命令行标志是为生产使用而设计的。然而,它作为一种工具非常有用,可以用来探测一个完全不透明的虚拟机的内部工作。