JVM两种类型的区别:
曾几何时,我也敲打过无数次这样的命令:
然而之前的我都只关心过版本号,也就是第一行的内容。今天,我们就来看看第3行输出的内容:JVM的类型和工作模式。
其实说Server和Client是JVM的两种工作模式是不准确的,因为它们就是不同的虚拟机,因此应该说有两种类型的JVM。
第三行的输出中可以看到:JVM的名字(HotSpot)、类型(Client)和build ID(24.79-b02) 。除此之外,我们还知道JVM以混合模式(mixed mode)在运行,这是HotSpot默认的运行模式,意味着JVM在运行时可以动态的把字节码编译为本地代码。我们也可以看到类数据共享(class data sharing)是开启(即第三行最后的sharing)的。类数据共享(class data sharing)是一种在只读缓存(在jsa文件中,”Java Shared Archive”)中存储JRE的系统类,被所有Java进程的类加载器用来当做共享资源,它可能在经常从jar文档中读所有的类数据的情况下显示出性能优势。
-Server VM启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升。
当虚拟机运行在-client模式的时候,使用的是一个代号为C1的轻量级编译器, 而-server模式启动的虚拟机采用相对重量级,代号为C2的编译器. C2比C1编译器编译的相对彻底,,服务起来之后,性能更高.
前段时间有个同事给我发了个java跟c++性能比较的文章,其中有个对比图引起了我的兴趣,意外的是,我感兴趣的不是java和c++的对比,而是java -Server模式和java -client模式的对比。从来没想到两者间的性能有如此巨大的差别。而在后来自己的亲身测试中发现确实如此。
下面是我看到的那个对比图:
图中最显著的就是JVM client模式和Server模式关于method call的对比,那个差别不是一般的大,在后来的测试中发现,相差至少有10倍。
如果想要在windows平台下从Client JVM切换到Server JVM,需要下载JDK而非JRE。打开JDK安装目录(即%JAVA_HOME%):我们可以看到%JAVA_HOME%\jre\bin下有一个server和client文件夹,这里面各有一个jvm.dll,但是大小不同,这就说明了它们是不同的JVM的文件
打开 %JAVA_HOME%\jre\lib\i386\jvm.cfg文件(正如第一幅图所见,我这里安装的是32JDK,其他版本的JDK可能不是i386文件夹)(注意是JDK文件夹下的jre,而非和JDK同级的jre6/7/8),会注意到以下内容(灰色选中部分):
再看看下方的配置,第一行就配置了使用client方式,因此首选使用client模式的JVM,这就是为什么一开始的java -version命令会输出Java HotSpot(TM) Client VM的原因了。现在将第33、34行配置交换一下,再在命令行中输入java -version,则会得到以下结果:
JVM工作在Server模式可以大大提高性能,但应用的启动会比client模式慢大概10%。当该参数不指定时,虚拟机启动检测主机是否为服务器,如果是,则以Server模式启动,否则以client模式启动,J2SE5.0检测的根据是至少2个CPU和最低2GB内存。
当JVM用于启动GUI界面的交互应用时适合于使用client模式,当JVM用于运行服务器后台程序时建议用Server模式。
JVM在client模式默认-Xms是1M,-Xmx是64M;JVM在Server模式默认-Xms是128M,-Xmx是1024M。我们可以通过运行:java -version来查看jvm默认工作在什么模式。
JVM工作模式:
其实这两个是JVM工作的模式。JVM有以下几种模式:-Xint, -Xcomp, 和 -Xmixed。从上图的输出结果中也可以看到,mixed是JVM的默认模式,其实在文章一开始的时候就提到了
-Xmixed代表混合模式(mixed mode),前面也提到了,混合模式是JVM的默认工作模式。它会同时使用编译模式和解释模式。对于字节码中多次被调用的部分,JVM会将其编译成本地代码以提高执行效率;而被调用很少(甚至只有一次)的方法在解释模式下会继续执行,从而减少编译和优化成本。JIT编译器在运行时创建方法使用文件,然后一步一步的优化每一个方法,有时候会主动的优化应用的行为。这些优化技术,比如积极的分支预测(optimistic branch prediction),如果不先分析应用就不能有效的使用。这样将频繁调用的部分提取出来,编译成本地代码,也就是在应用中构建某种热点(即HotSpot,这也是HotSpot JVM名字的由来)。使用混合模式可以获得最好的执行效率。
-Xint代表解释模式(interpreted mode),-Xint标记会强制JVM以解释方式执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。
-Xcomp代表编译模式(compiled mode),与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。这听起来不错,因为这完全绕开了缓慢的解释器。然而,很多应用在使用-Xcomp也会有一些性能损失,但是这比使用-Xint损失的少,原因是-Xcomp没有让JVM启用JIT编译器的全部功能。因此在上图中,我们并没有看到-Xcomp比-Xmixed快多少。
在都使用Client JVM的前提下,混合模式下,平均耗时150ms,然而在解释模式下,平均耗时超过1600ms,这基本上是10倍以上的差距。