[转]你所不知道的五件事情--JVM的命令行选项

2023-11-21 07:18

本文主要是介绍[转]你所不知道的五件事情--JVM的命令行选项,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这是Ted Neward在IBM developerWorks中5 things系列文章中的一篇,讲述了关于JVM命令行参数的一些应用窍门,值得大家学习。(2010.09.01最后更新)

摘要:Java虚拟机有数百个命令行选项,只有经验十分丰富的Java开发员才会使用这些选项去调优Java运行时环境。学习如何监控并记录编译器性能,禁用显示的垃圾收集(System.gc()),扩展JRE,及其它。

    JVM是Java应用程序功能与性能背后的实际工作者,大部分Java开发者认为这是理所当然的。然而我们中很少有人真正地理解JVM是如何做到这些事的--如,分配并收集垃圾对象,摆弄线程,打开及关闭文件,解释和/或使用JIT编译Java字节码,以及其它任务。
    不熟悉JVM不仅会使你在应用程序的性能方面付出代价,而且当JVM出了某些问题时,还很难进行修复。
    5 things系列的这篇文章介绍一些好用的命令行JVM选项,你可以使用它们去诊断并调优Java虚拟机的性能。

1. DisableExplicitGC
    我无法告诉你我已经多少次被要求就应用程序性能问题进行咨询了,而我只是简单地对代码文件执行grep命令就能发现如清单1所示的程序--这就是早期Java性能的反模式:

Listing 1. System.gc();

//  We just released a bunch of objects, so tell the stupid
//  garbage collector to collect them already!
System.gc();

显式地执行垃圾收集器确实是个坏主意--这就像把你自己与一个疯狂的斗牛犬锁在电话亭中那样。虽然该调用的确切语义依赖于具体的实现,但假设你的JVM运行着一个分代垃圾收集器(大多数JVM也正是如此),System.gc()方法强制要求VM对Heap进行"全面清扫",即便有些并不是必要的。一般地,全面清扫的开销要比常规GC操作要大几个数量级,而常规GC操作的开销只会产生纯数学的负作用。
     但不要相信我的话--为了这个特殊的人为错误,Sun的工程师们为我们提供了一个JVM选项:-XX:+DisableExplicitGC选项自动地将System.gc()调用置为无用操作,给你一个机会去执行程序,并让你自己看看System.gc()是否已经帮助或损害整个JVM的执行。

2. HeapDumpOnOutOfMemoryError
    你肯定曾经遇到过JVM不断死掉的情况,即抛出OutOfMemoryError,在你的一生中似乎都不能设置一个调试器去捕获这个错误,并看看是出了什么问题?像这些不时发生且/或无法确定的问题能使一个开发员完全疯掉。
    你所想的,就是在在JVM快死掉时能够捕获Heap的快照--这正是命令-XX:+HeapDumpOnOutOfMemoryError所要做的。
    运行该命令就是告诉JVM创建一个"Heap转储快照",并将它保存为一个文件以便于处理,常常使用jhat工具(在前一篇文章中我有介绍过)。使用相应的命令-XX:HeapDumpPath,就指定被保存文件的确切路径。(不论文件保存在何处,要先确保文件系统和/或Java进程有必要的仅限配置能在那儿写文件。) 

3. bootclasspath
    偶尔地,将某个类,该类不同于原有的或以某种方式扩展而得到的JRE所存储的类,置于类路径中是有用的。(一个例子就是新的Java Crypto API适配器)。如果你想扩展JRE,那么你的定制实现需要能用于引导ClassLoader,该ClassLoader会加载java.lang.Object以及它在rt.jar中的所有同族成员。
    尽管你可以打开rt.jar并将你定制实现或新的包放入其中,但在技术上这就违反了当初你在下载JDK时所同意的协议。
    相反地,应该使用JVM自己的-Xbootclasspath选项,以及它的兄弟选项-Xbootclasspath/p-Xbootclasspath/a
    -Xbootclasspath允许你设置整个引导类路径,该路径一般地必须包含一个针对rt.jar的引用,再加上一批随JDK发布但不是rt.jar一部分的其它JAR文件。-Xbootclasspath/p会向已有引导类路径中预置值,然后-Xbootclasspath/a会将它连接起来。
    例如,如果你已经修改了原有的java.lang.Integer,并将修改后的程序放入子目录,mods,然后参数-Xbootclasspath/a mods将会在加载原有默认Integer类之前加载这个新的Integer实现。

4. verbose
    对于任何类型的Java应用,-verbose都是头等有用的诊断工具。该选项有三个子选项:gcclassjni
    一般地,如果JVM垃圾收集器在运行并导致了低下的性能,那么gc就是开发员们第一次想要弄清楚的地方。不幸地是,解释gc的输出需要些技巧,这足够成为一整本书的主题了。更糟地是,在命令行窗口打印出的输出对于不同的Java发行版是不同的,或者对于不同的JVM也是不同的,这造成难以对其进行正确地解释。
    一般来说,如果垃圾收集器是分代收集器(大多数"企业级"VM正是如此),会有一些布尔型选项去指定是否使用完全清除;在Sun的JVM中,这样的选项会以[Full GC ...]的形式出现在GC输出行的开头。
    class会是一个生命保护者,它尝试着诊断ClassLoader和/或不匹配的类冲突。它不仅会报告类是在何时被加载的,而且也会报告类是从何处被加载的,包括JAR文件的路径,如果这个类来自于一个JAR的话。
    jni很少用到,除非你有使用JNI和原生库。当启用该选项时,它会报告各种JNI事件,例如原生库何时被加载的,以及方法何时被绑定的;另外,该报告输出会由于不同的Java版或JVM实现而不尽相同。

5. 命令行-X
    我已经列出了一些JVM提供的且我比较喜欢的命令行选项,但还有更多的选项你自己就能发现到。运行命令行参数-X列出所有JVM支持的非标准的(但多数就是安全的)参数--就像这些:
    -Xint,使JVM以解释模式进行运行(对于测试JIT编译器是否真的作用到你的程序,或是证明你是否有Bug在JIT编译器中,该选项是很用的)。
    -Xloggc:,该参数所做的与-verbose:gc相同,但它会把日志记录到一个文件中,而不是一股脑地输出在命令窗口中。
    JVM命令行选项改了一次又一次,所以隔一段时间再去看会是一个好主意。这种区别就好像是,花上一整夜金城汤池盯着你的显示器,或者是下午五点就回家与爱人和孩子享用美餐(或是在Mass Effect 2中屠杀敌人,这取决于你的偏好)。

结论
    命令行选项的本意不是为了在产品环境中永久使用--事实上,除了你(可能)最终用于调优JVM垃圾收集器的选项之外,非标准的命令选项都不会被刻意地用到产品中。但作为能够窥探到完全不透明的虚拟机的内部工部情形的工具,它们是无价的。
    5 things系列的下一篇文章:Java日常工具。

这篇关于[转]你所不知道的五件事情--JVM的命令行选项的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400730

相关文章

Java中对象的创建和销毁过程详析

《Java中对象的创建和销毁过程详析》:本文主要介绍Java中对象的创建和销毁过程,对象的创建过程包括类加载检查、内存分配、初始化零值内存、设置对象头和执行init方法,对象的销毁过程由垃圾回收机... 目录前言对象的创建过程1. 类加载检查2China编程. 分配内存3. 初始化零值4. 设置对象头5. 执行

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程

《SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程》本文详细介绍了如何在虚拟机和宝塔面板中安装RabbitMQ,并使用Java代码实现消息的发送和接收,通过异步通讯,可以优化... 目录一、RabbitMQ安装二、启动RabbitMQ三、javascript编写Java代码1、引入

spring-boot-starter-thymeleaf加载外部html文件方式

《spring-boot-starter-thymeleaf加载外部html文件方式》本文介绍了在SpringMVC中使用Thymeleaf模板引擎加载外部HTML文件的方法,以及在SpringBoo... 目录1.Thymeleaf介绍2.springboot使用thymeleaf2.1.引入spring

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在