现在的JVM运行Java程序(和其它的兼容性语言)时在高效性和稳定性方面做的非常出色。自适应内存管理、垃圾收集、及时编译、动态类加载、锁优化——这里仅仅列举了某些场景下会发生的神奇的事情,但他们几乎不会直接与普通的程序员相关。在运行时,JVM会不断的计算并优化应用或者应用的某些部分。

虽然有了这种程度的自动化(或者说有这么多自动化),但是JVM仍然提供了足够多的外部监控和手动调优工具。在有错误或低性能的情况下,JVM必须能够让专家调试。顺便说一句,除了这些隐藏在引擎中的神奇功能,允许大范围的手动调优也是现代JVM的优势之一。有趣的是,一些命令行参数可以在JVM启动时传入到JVM中。一些JVM提供了几百个这样的参数,所以如果没有这方面的知识很容易迷失。这系列博客的目标是着重讲解日常相关的一些参数以及他们的适用场合。我们将专注于Java6的Sun/Oracle HotSpot JVM,大多数情况下,这些参数也会适用于其他一些流行的JVM里。

-server and -client

有两种类型的 HotSpot JVM,即”server”和”client”。服务端的VM中的默认为堆提供了一个更大的空间以及一个并行的垃圾收集器,并且在运行时可以更大程度地优化代码。客户端的VM更加保守一些(校对注:这里作者指客户端虚拟机有较小的默认堆大小),这样可以缩短JVM的启动时间和占用更少的内存。有一个叫”JVM功效学”的概念,它会在JVM启动的时候根据可用的硬件和操作系统来自动的选择JVM的类型。具体的标准可以在这里找到。从标准表中,我们可以看到客户端的VM只在32位系统中可用。

如果我们不喜欢预选(校对注:指JVM自动选择的JVM类型)的JVM,我们可以使用-server和-client参数来设置使用服务端或客户端的VM。虽然当初服务端VM的目标是长时间运行的服务进程,但是现在看来,在运行独立应用程序时它比客户端VM有更出色的性能。当应用的性能非常重要时,我推荐使用-server参数来选择服务端VM。一个常见的问题:在一个32位的系统上,HotSpot JDK可以运行服务端VM,但是32位的JRE只能运行客户端VM。

-version and -showversion

当我们调用“java”命令时,我们如何才能知道我们安装的是哪个版本的Java和JVM类型呢?在同一个系统中安装多个Java,如果不注意的话有运行错误JVM的风险。在不同的Linux版本上预装JVM这方面,我承认现在已经变的比以前好很多了。幸运的是,我们现在可以使用-version参数,它可以打印出正在使用的JVM的信息。例如:

$ java -version
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)

-version参数在打印完上述信息后立即终止JVM。还有一个类似的参数-showversion可以用来输出相同的信息,但是-showversion紧接着会处理并执行Java程序。因此,-showversion对几乎所有Java应用的命令行都是一个有效的补充。你永远不知道你什么时候,突然需要了解一个特定的Java应用(崩溃时)使用的JVM的一些信息。在启动时添加-showversion,我们就能保证当我们需要时可以得到这些信息。输出显示的是Java版本号(1.6.0_24)和JRE确切的build号(1.6.0_24-b07)。我们也可以看到JVM的名字(HotSpot)、类型(client)和build ID(19.1-b02) )。除此之外,我们还知道JVM以混合模式(mixed mode)在运行,这是HotSpot默认的运行模式,意味着JVM在运行时可以动态的把字节码编译为本地代码。我们也可以看到类数据共享(class data sharing)是开启的,类数据共享(class data sharing)是一种在只读缓存(在jsa文件中,”Java Shared Archive”)中存储JRE的系统类,被所有Java进程的类加载器用来当做共享资源。类数据共享(Class data sharing)可能在经常从jar文档中读所有的类数据的情况下显示出性能优势。

-Xint, -Xcomp, 和 -Xmixed

-Xint和-Xcomp参数和我们的日常工作不是很相关,但是我非常有兴趣通过它来了解下JVM。在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。这听起来不错,因为这完全绕开了缓慢的解释器。然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器在运行时创建方法使用文件,然后一步一步的优化每一个方法,有时候会主动的优化应用的行为。这些优化技术,比如,积极的分支预测(optimistic branch prediction),如果不先分析应用就不能有效的使用。另一方面方法只有证明它们与此相关时才会被编译,也就是,在应用中构建某种热点。被调用很少(甚至只有一次)的方法在解释模式下会继续执行,从而减少编译和优化成本。

注意混合模式也有他自己的参数,-Xmixed。最新版本的HotSpot的默认模式是混合模式,所以我们不需要特别指定这个标记。我们来用对象填充HashMap然后检索它的结果做一个简单的用例。每一个例子,它的运行时间都是很多次运行的平均时间。

$ java -server -showversion Benchmark
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Server VM (build 19.1-b02, mixed mode)
 
Average time: 0.856449 seconds
$ java -server -showversion -Xcomp Benchmark
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Server VM (build 19.1-b02, compiled mode)
 
Average time: 0.950892 seconds
$ java -server -showversion -Xint Benchmark
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Server VM (build 19.1-b02, interpreted mode)
 
Average time: 7.622285 seconds

当然也有很多使-Xcomp表现很好的例子。特别是运行时间长的应用,我强烈建议大家使用JVM的默认设置,让JIT编译器充分发挥其动态潜力,毕竟JIT编译器是组成JVM最重要的组件之一。事实上,正是因为JVM在这方面的进展才让Java不再那么慢。

JVM参数(一)JVM类型以及编译器模式的更多相关文章

  1. JVM实用参数(一)JVM类型以及编译器模式

    JVM实用参数(一)JVM类型以及编译器模式 原文地址:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-1-jvm-types ...

  2. JVM参数配置 java内存区域

    java内存区域 一些基本概念 http://www.importnew.com/18694.html https://www.cnblogs.com/wangyayun/p/6557851.html ...

  3. JVM 参数及各部分含义(转)

    转自:https://www.jianshu.com/p/1c6b5c2e95f9 JVM参数分类 JVM参数分为标准参数和非标准参数: 标准参数: "-"开头的参数,如-clie ...

  4. JVM参数(二)参数分类和即时(JIT)编译器诊断

    在这个系列的第二部分,我来介绍一下HotSpot JVM提供的不同类别的参数.我同样会讨论一些关于JIT编译器诊断的有趣参数. JVM 参数分类 HotSpot JVM 提供了三类参数.第一类包括了标 ...

  5. jvm参数优化

    一.HotSpot JVM 提供了三类参数 现在的JVM运行Java程序(和其它的兼容性语言)时在高效性和稳定性方面做的非常出色.例如:自适应内存管理.垃圾收集.及时编译.动态类加载.锁优化等.虽然有 ...

  6. Intellij IDEA 设置启动JVM参数

    目录 采用CMS垃圾回收配置: 采用G1垃圾回收配置: 参数说明: 通用参数: CMS机制才有的参数: G1机制才有的参数: 参考: 打开 IDEA 安装目录,看到有一个 bin 目录,其中有两个 v ...

  7. JVM性能优化, Part 2 ―― 编译器

    作为JVM性能优化系列文章的第2篇,本文将着重介绍Java编译器,此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化,Part 1″中对JVM的介绍).Eva Andreasson ...

  8. JVM参数及调优

    ## 3.2.1 JVM参数及调优 ### 调优基本概念 在调整JVM性能时,通常有三个组件需要考虑:1. 堆大小调整2. 垃圾收集器调整3. JIT编译器 大多数调优选项都与调整堆大小和选择合适的垃 ...

  9. JVM参数概述

    标准参数(-) 所有的JVM实现都必须实现这些参数的功能,而且向后兼容. 通过命令 java 查看如下: 用法: java [-options] class [args...] (执行类) 或 jav ...

随机推荐

  1. MYSQL 基于GTID的复制

    1.概述 从MYSQL5.6 开始,mysql开始支持GTID复制. 基于日志点复制的缺点: 从那个二进制日志的偏移量进行增量同步,如果指定错误会造成遗漏或者重复,导致数据不一致. 基于GTID复制: ...

  2. Java小bug

    1.使用split函数,将字符串按"."分开,写法如下: String str = "a.b.c"; String[] items = str.split(&q ...

  3. Appcan 3.2 Switch操作

    Appcan3.0,有了很多不错的东西,但官方的文档还是那么的不靠谱. 我将记录下,我学习到的东西. 显示2个switch <div class="ub ub-pe"> ...

  4. hdu 1047 (big integer sum, fgets or scanf, make you func return useful infos) 分类: hdoj 2015-06-18 08:21 39人阅读 评论(0) 收藏

    errors made, boundary conditions, <= vs < , decreasing vs increasing , ++, –, '0'/'1' vs 0/1 p ...

  5. iOS开发:XCTest单元测试(附上一个单例的测试代码)

    测试驱动开发并不是一个很新鲜的概念了.在我最开始学习程序编写时,最喜欢干的事情就是编写一段代码,然后运行观察结果是否正确.我所学习第一门语言是c语言,用的最多的是在算法设计上,那时候最常做的事情就是编 ...

  6. ViewHolder简洁写法

    ViewHolder holder = null;         if(convertView == null){                 convertView = mInflater.i ...

  7. 浅谈C#中的接口和抽象类

    C#中接口为"其他方面互不相干"的类型提供公共的服务和特征:C#中class只支持但继承,使用接口却支持多继承,例如:C#中System.String是从System空间中的4个i ...

  8. c语言scanf返回值

    1. scanf 函数是有返回值的,它的返回值可以分成三种情况 1) 正整数,表示正确输入参数的个数.例如执行 scanf("%d %d", &a, &b); 如果 ...

  9. IAR for msp430 MDK中 warning: #223-D: function "xxx" declared implicitly 解决方法

    今天在EINT的范例里添加了一个函数,即eint.c中添加了一个datawrite()的函数,并在主函数main.c中调用,编译便警告 warning: #223-D: function " ...

  10. c++标准模板库algorithm头文件中accumulate算法的代码

    template <typename T>T algorithm(T* start, T* end, T total)//把[start, end)标记范围内所有元素累加到total中{  ...