本文是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.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/amods参数将新Integer放在默认的参数前面。

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版本中,输出会发生变化。

5.Command-line-X

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

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

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

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

结束语

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

5个jvm命令的更多相关文章

  1. JVM命令行工具&垃圾收集器&垃圾收集策略思维导图

    1.JVM命令行工具 2.垃圾回收算法 3.垃圾收集器

  2. 这些JVM命令配置参数你知道吗?

    JVM是多数开发人员视为理所当然的Java功能和性能背后的重负荷机器.然而,我们很少有人能理解JVM是如何进行工作的—像任务分配和垃圾收集.转动线程.打开和关闭文件.中断和/或JIT编译Java字节码 ...

  3. 【JVM命令系列】jstat

    命令基本概述 Jstat是JDK自带的一个轻量级小工具.全称"Java Virtual Machine statistics monitoring tool",它位于java的bi ...

  4. 【JVM命令系列】jstack

    jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使 ...

  5. 【JVM命令系列】javap

    命令基本概述 javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码.通过它,可以对照源代码和字节码,从而了解很多编译器内部的工作.可以在命令行窗口先用javap -help看下j ...

  6. 【JVM命令系列】jmap

    命令基本概述 Jmap是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本.打印出某个java进程(使用pid)内存内的,所有'对象'的情况(如:产生那些对象,及其数量 ...

  7. JVM命令

    jstack--jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息: jinfo--jinfo可以输出并修改运行时的java 进程的opts.用处比较简单 ...

  8. JVM命令-java服务器故障排查

    一.top(Linux命令) 执行top命令:    (查看进程15477的详细情况,下文用到) 系统信息(前五行): 第1行:Top 任务队列信息(系统运行状态及平均负载),与uptime命令结果相 ...

  9. jvm 命令

    jps  jps主要用来输出JVM中运行的进程状态信息.语法格式如下: jps [options] [hostid] 如果不指定hostid就默认为当前主机或服务器. -q 不输出类名.Jar名和传入 ...

随机推荐

  1. <Sicily>Tiling a Grid With Dominoes

    一.题目描述 We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by on ...

  2. Ubuntu18.04 解压zip文件乱码的解决方法

    在Ubuntu的系统下解压zip文件的时候居然出现了乱码,通过查找网上的资料,解决的办法有两种 一.通过unzip行命令解压,指定字符集,由于zip格式中并没有指定编码格式,Windows下生成的zi ...

  3. NodeJS学习笔记 进阶 (10)Nodejs 进阶:log4js入门实例(ok))

    个人总结:读完这篇文章讲解了log4js的使用,具体更多可以参考npmjs上看,读完这篇需要15分钟. 摘选自网络 对于线上项目用来说,日志是非常重要的一环.log4js是使用得比较多的一个日志组件, ...

  4. 关联Anaconda和最新Pycharm2018.3.2

    在Anaconda和Pycharm 2018.3.2 x64都安装好之后,进行Anaconda 与Pycharm的关联操作 首先File -->New Project 打开以后切记要把Proje ...

  5. python web开发 框架 模板 MVC

    我是跟着廖雪峰老师学习的,对于我这样的纯小白来说,跟着他的网站学习,简直是被妈妈抱在怀里一样无忧无虑,这样的学习本来没有记录下来的必要,但是由于我的粗心大意,经常会出现一些错误,所以我决定把这些错误记 ...

  6. 三 概要模式 2) MR倒排索引、性能分析、搜索干扰词。

    二  倒排索引     倒排索引(英语:Inverted index),也常被称为反向索引.置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射. ...

  7. ADL & 实参相依的查找 & 成员与非成员的查找

    也就是会根据实参,所处在的名字空间,来查找对应名字空间里面的函数. 对于<<也是常见的场景,会根据实际要打印出来的下一个操作数,来决定调用哪个命名空间里面的函数. 注意,不同命名空间里面的 ...

  8. python的开发工具UliPad安装篇

    之前文章里写过一个搭建windows下搭建Selenium+Eclipse+Python环境,如今认为这个Eclipse太大了,太笨重了,重新启动又慢,像Python脚本轻级语言,不是必需用那么大的工 ...

  9. Raphaeljs入门到精通(一)

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  10. IDEA创建maven项目之后无法编写java类

    在创建Maven web项目之后无法再java文件夹下面创建java类,这里我可以教一下大家 选择你的文件夹,鼠标点击右键,出现下图所显示的,你可以按照下图所显示的步骤进行操作