5个JVM命令行标志,值得你知道

本文是Neward & Associates的总裁Ted Neward为developerworks独家撰稿“你不知道5个……”系列中的一篇,JVM是多数开发人员视为理所当然的Java功能和性能背后的重负荷机器。然而,我们很少有人能理解JVM是如何进行工作的—像任务分配和垃圾收集、转动线程、打开和关闭文件、中断和/或JIT编译Java字节码,等等。

不熟悉JVM将不仅会影响应用程序性能,而且当JVM出问题时,尝试修复也会很困难。

本文将介绍一些命令行标志,您可以使用它们来诊断和调优您的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.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/amods参数将新Integer放在默认的参数前面。

3.Command-line-X

我列出了JVM中提供的我喜欢的命令行选项,但是还有一些更多的需要您自己发现,运行命令行参数-X,列出JVM提供的所有非标准(但大部分都是安全的)参数—例如:

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

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

JVM命令行选项时常发生变化,因此,定期查看是一个好主意。甚至,您深夜盯着监控器和下午5点回家和妻子孩子吃顿晚饭,(或者在Mass Effect 2中消灭您的敌人,根据您的喜好),它们都是不一样的。

4.HeapDumpOnOutOfMemoryError

您有没有经历过这样的情况:JVM不能使用,不断抛出OutOfMemoryError,而您又不能为自己创建调试器来捕获它或查看出现了什么问题?像这类偶发和/或不确定的问题,通常使开发人员发疯。

买者自负

并不是任何VM都支持所有命令行标志,Sun/Oracle的VM除外。查明一个标志是否被支持的最好方法是试用它,看它是否正常工作。倘若这些标志在技术上是不支持的,那么,使用它们您要承担全部责任。如果这些标志中的任何一个使您的代码、您的数据、您的服务器或您的一切消失得无影无踪,我、Sun/Oracle和IBM都将不负责任。为以防万一,建议先在虚拟(非常生产)环境中实验。

在这个时刻您想要的是,在JVM消亡之际捕获堆的一个快照——正好-XX:+HeapDumpOnOutOfMemoryError命令可以完成这一操作。

运行该命令通知JVM拍摄一个“堆转储快照”,并将其保存在一个文件中以便处理,通常使用jhat实用工具(我在上一篇文章中介绍过)。您可以使用相应的-XX:HeapDumpPath标志指定到保存文件的实际路径。(不管文件保存在哪,务必确保文件系统和/或Java流程必须要有权限配置,可以在其中写入。)

4.verbose

对于虚拟的或任何类型的Java应用程序,-verbose是一个很有用的一级诊断使用程序。该标志有三个子标志:gc、class和jni。

开发人员尝试寻找是否 JVM 垃圾收集器发生故障或者导致性能低下,通常首先要做的就是执行 gc。不幸的是,解释 gc 输出很麻烦 — 足够写一本书。更糟糕的是,在命令行中打印的输出在不同的 Java 版本中或者不在不同的 JVM 中会发生改变,这使得正确解释变得更难。

一般来说,如果垃圾收集器是一个分代收集器(多数“企业级”VMs都是)。某种虚拟标志将会出现,来指出一个全部清扫GC通路;在Sun JVM中,标志在GC输出行的开始以“[FullGC...]”形式出现。

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

jni很少使用,除了使用JNI或本地库时。打开时,它将报告各种JNI事件,比如,本地库何时加载,方法何时弹回;再一次强调,在不同JVM版本中,输出会发生变化。

结束语

在生产环境中,命令行标志不是为永久使用而设计的——事实上,除了您终止用来调优JVM垃圾收集器的标志,没有一个非标准命令行标记是专用于生产使用的。但是,作为工具来刺探在其他方面完全不透明的虚拟机的内部工作,是非常有用的。

原文来自  java TechFox IT技术论

时间: 2024-10-29 02:55:59

5个JVM命令行标志,值得你知道的相关文章

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

本文是Neward & Associates的总裁Ted Neward为developerworks独家撰稿"你不知道5个--"系列中的一篇,JVM是多数开发人员视为理所当然的Java功能和性能背后的重负荷机器.然而,我们很少有人能理解JVM是如何进行工作的-像任务分配和垃圾收集.转动线程.打开和关闭文件.中断和/或JIT编译Java字节码,等等. 不熟悉JVM将不仅会影响应用程序性能,而且当JVM出问题时,尝试修复也会很困难. 本文将介绍一些命令行标志,您可以使用它们来诊断和

JVM命令行选项及GC日志

一.设置参数 在使用eclipse编译器的时候,可以采用以下的运行方式来设置虚拟机的参数: 具体参数的设置: 这里先以打印回收时间,回收信息为例 二.打印信息解释: 三.一些常用的jvm参数 -XX:+PrintGCTimeStamps: 打印此次垃圾回收距离jvm开始运行的所耗时间 -XX:+PrintGCDeatils 打印垃圾回收的细节信息 -Xloggc:<filename> 将垃圾回收信息输出到指定文件 -XX:+PrintGCDateStamps 需要打印日历形式的时间戳选项 -X

java自带命令行工具(jmap,jhat,jinfo)

(1)JMAP 1.作用 打印进程,core文件,和远程进程的共享对象存储map或堆存储器的详细信息. 2.使用 jmap [ options ] pid jmap [ options ] executable core jmap [ options ] [ pid ] [email protected] ] remote-hostname-or-IP 如果指定的进程是在64位Java虚拟机(JVM)上运行,那么你可能需要指定-J-d64选项,例如:jmap -J-d64 -heap pid.

常用的jvm命令

(1)jps -lv 列出所有java进程 第一个参数是pid: 第二个为jvm参数和完整的执行类名 (2)jinfo <pid> 描述:输出给定 java 进程所有的配置信息.包括 java 系统属性和 jvm 命令行标记等. (3)jstack <pid> 为指定的线程输出 java 的线程堆栈信息,包括了进程里的所有线程.每一个线程 frame ,包括类全名,方法名,代码行. (4)jstat -gcutil <pid> <interval> 查看ja

C#命令行编辑器csc.exe

csc.exe是.NET Framework SDK中的一个工具,当然用VS舒服多了...不怕麻烦或者小硬盘的可以用用看,下面是些基本编辑,编译,调试操作(很不详细,详细请看MSDN :) ):1.配置C#命令行编辑器:我的电脑 - 属性 - 高级 - 环境变量 - 系统变量列表对话框 - 双击Path变量 - 在当前路径值的末尾加入(路径变量里各值用分号区隔): C:\Windows\Microsoft.NET\Framework\v2.0.50727 (注意,路径和版本号会因为你的安装和下载

命令行参数(flag包)

命令行参数 命令行参数可以直接通过 os.Args 获取,另外标准库的 flag 包专门用于接收和解除命令行参数 os.Args 简单的只是从命令行获取一个或一组参数,可以直接使用 os.Args.下面的这种写法,无需进行判断,无论是否提供了命令行参数,或者提供了多个,都可以处理: // 把命令行参数,依次打印,每行一个 func main() { for _, s := range os.Args[1:] { fmt.Println(s) } } flag 基本使用 下面的例子使用了两种形式的

JVM虚拟机性能监控与调优(JDK命令行、JConsole)

很多资料在介绍JDK命令行工具时并不是在Java8环境下,因此还在使用过时的永久区系列的参数,给一些读者造成困难. Java8使用Metaspace(元空间)代替永久区,对于64位平台,为了压缩JVM对象中的_klass指针的大小,引入了类指针压缩空间(Compressed Class Pointer Space) .关于这点,可以参考博客https://blog.csdn.net/liang0000zai/article/details/51168095. 1. JDK命令行工具 在JDK的开

你值得了解的 10 个有趣的 Linux 命令行小技巧

摘要: 我非常喜欢使用命令,因为它们比 GUI(图形用户界面)应用程序对 Linux 系统提供更多的控制,因此,我一直在寻找一些有趣的方法让 Linux 的操作变得简单好玩,主要是基于终端操作. 当我们发现使用 Linux 的新技巧时,尤其是像我这样的命令行极客,我们总会感到非常来劲. 我非常喜欢使用命令,因为它们比 GUI(图形用户界面)应用程序对 Linux 系统提供更多的控制,因此,我一直在寻找一些有趣的方法让 Linux 的操作变得简单好玩,主要是基于终端操作. 当我们发现使用 Linu

Linux -高阶命令行技巧

熟练地操作命令行是一项常常被我们忽视的技能,又或者说我们将它看的太过神秘.不过作为一名软件工程师,掌握这一技能可以很大程度上提升我们工作的灵活性,提高工作效率.这篇文章是我在与 Linux 打交道的过程中总结出的一些小技巧.有些很基础,有些也相当专业,不太好懂.这篇文章不长,不过如果你能在工作中充分使用这里介绍的技能的话,那你也知之甚多了. 这里的许多内容一开始已出现在 Quora,但考虑到 Github 的用户性质,他们比我有天赋而且可以随时提出改进意见,因此使用 Github 更合适.如果你