本人博客原文:http://www.deleiguo.com/archives/172
转发请附带原文地址
简介
基本上一开始学习Java,就接触到第一个Java的命令:java -version
这个命令最常用的就是用来查看当前服务器的JDK环境版本,以此验证服务器环境变量是否已正确的设置好JDK。
最常见的结果一般有两种:
- Sun JDK:
delei@DeleitekiMBP:~$ java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
- Open JDK:
root@ubuntu-server:~# java -version
java version "1.7.0_95"
OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.15.10.1)
OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
第一行:JDK的版本号
第二行:JDK的运行环境
但第三行是指的什么,在一开始没留意也不理解这一行包含着哪些信息,这里以Sun JDK为例来稍微深入看一下.
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
-
Java HotSpot(TM)
-
64-Bit
- 如果安装的是64位的则是64-bit,如果安装是32位,则为32-bit。
- 这里不是服务器的操作系统,而是指的当前安装JDK
Server VM
Server VM
Client VM
mixed mode
mixed mode:混合模式
class data sharing:类数据共享
interpreted mode:解释模式
JVM类型
首先要知道的的是Server VM和Client VM可以理解是不同的虚拟机。
如果操作系统是64位的,只能是Server VM,Client VM只有在32位上才有。Oracle官方
Server VM和Client VM有什么区别?在官网的FAQ中有如下的描述:
JIT Compiler
1.What's the difference between the -client and -server systems?
These two systems are different binaries. They are essentially two different compilers (JITs)interfacing to the same runtime system. The client system is optimal for applications which need fast startup times or small footprints, the server system is optimal for applications where the overall performance is most important. In general the client system is better suited for interactive applications such as GUIs. Some of the other differences include the compilation policy,heap defaults, and inlining policy.
大致翻译:
这两个JVM采用不同的编译器。
Client JVM适合快速启动和较小内存的,它适合强调交互的应用,比如GUI(桌面级应用界面);
Server JVM则是偏重执行时候的效率的。
其他不同的地方"编译策略"、"默认堆大小"、"内嵌策略"
2.Where do I get the server and client systems?
Client and server systems are both downloaded with the 32-bit Solaris and Linux downloads. For 32-bit Windows, if you download the JRE, you get only the client, you'll need to download the SDK to get both systems.
For 64-bit, only the server system is included. On Solaris, the 64-bit JRE is an overlay on top of the 32-bit distribution. However, on Linux and Windows, it's a completely separate distribution.
主要内容翻译:
在32位的系统中,如果下载JRE,则只有client;
从Java SE 5.0开始,在64位的系统中,默认的时候Server,32位的默认
以上是从官方得到的原理/规范使用上的一些说明。接下来看在实际当中,如何切换Server VM和Client VM:
- 想要在windows系统中进行切换,需要下载JDK而不是JRE;
- 在Windows 系统中,找到JDK(%JAVA_HOME%)安装的目录
/jre/lib
,该目录下会有server
和client
两个不同的目录;
命令切换(推荐)
在CMD/终端命令中,执行java -server -version
和java -client -version
即可切换;修改文件(永久切换)
在jre/lib/i386/
(32位的JDK有i386文件夹),编辑修改jvm.cfg文件
# List of JVMs that can be used as an option to java, javac, etc.
# Order is important -- first in this list is the default JVM.
# NOTE that this both this file and its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
# Order is important -- first in this list is the default JVM.
第一行的配置则为默认的JVM,这里第一行是-client,所有默认是Client VM;
要想用Server VM,则将第二行与第三行调换位置保存即可;
应用场景
- 我们时常会在开发/生产环境中对web 服务器调整JVM的参数,一般来说目前服务器都是64位的,可以先用java -version来查看环境;
- 根据应用的场景需要,在jvm中加上
-server
参数;
JVM运行模式
在CMD/终端命令中,执行java -X
root@ubuntu-server:~# java -X
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
在此可以知道mixed是默认的模式;
JVM模式有:-Xint, -Xcomp, 和 -Xmixed
** -Xint**
在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。** -Xcomp**
-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。这听起来不错,因为这完全绕开了缓慢的解释器-Xmixed
混合模式(mixed mode),是JVM的默认工作模式。它会同时使用编译模式和解释模式。对于字节码中多次被调用的部分,JVM会将其编译成本地代码以提高执行效率;而被调用很少(甚至只有一次)的方法在解释模式下会继续执行,从而减少编译和优化成本。JIT编译器在运行时创建方法使用文件,然后一步一步的优化每一个方法,有时候会主动的优化应用的行为。这些优化技术,比如积极的分支预测(optimistic branch prediction),如果不先分析应用就不能有效的使用。这样将频繁调用的部分提取出来,编译成本地代码,也就是在应用中构建某种热点(即HotSpot,这也是HotSpot JVM名字的由来)。使用混合模式可以获得最好的执行效率。
在CMD/终端命令中,可以直接通过命令来切换模式:
root@ubuntu-server:~# java -Xint -version
java version "1.7.0_95"
OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.15.10.1)
OpenJDK 64-Bit Server VM (build 24.95-b01, interpreted mode)
root@ubuntu-server:~# java -Xcomp -version
java version "1.7.0_95"
OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.15.10.1)
OpenJDK 64-Bit Server VM (build 24.95-b01, compiled mode)
** 代码验证**
我们通过一个小的Java代码来验证下不同mode下的执行耗时(Server VM)
public class JVMModeTest {
private static void test() {//循环++
for (int i =0;i<1000000000;i++) {
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
test();
long end = System.currentTimeMillis();
System.out.println(end-start);//打印执行耗时
}
}
结果如下:
root@ubuntu-server:~/work/java$ java -Xcomp JVMModeTest
2
root@ubuntu-server:~/work/java$ java -Xint JVMModeTest
28562
root@ubuntu-server:~/work/java$ java -Xmixed JVMModeTest
18
由于即时编译器编译本地代码需要占用程序运行时间,要编译出优化程度更高的代码,所花费的时间可能更长;而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息,这对解释执行的速度也有影响。为了在程序启动响应速度与运行效率之间达到最佳平衡,HotSpot虚拟机还会逐渐启用分层编译(Tiered Compilation)[4]的策略,分层编译的概念在JDK 1.6时期出现,后来一直处于改进阶段,最终在JDK 1.7的Server模式虚拟机中作为默认编译策略被开启。分层编译根据编译器编译、优化的规模与耗时,划分出不同的编译层次,其中包括:
第0层,程序解释执行,解释器不开启性能监控功能(Profiling),可触发第1层编译。
第1层,也称为C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑。
第2层(或2层以上),也称为C2编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。
实施分层编译后,Client Compiler和Server Compiler将会同时工作,许多代码都可能会被多次编译,用Client Compiler获取更高的编译速度,用Server Compiler来获取更好的编译质量,在解释执行的时候也无须再承担收集性能监控信息的任务
注:
[1] 在虚拟机中习惯将Client Compiler称为C1,将Server Compiler称为C2。
参考/引用
http://my.oschina.net/itblog/blog/507822
http://ifeve.com/useful-jvm-flags-part-1-jvm-types-and-compiler-modes-2/
深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)
http://www.oracle.com/technetwork/java/hotspotfaq-138619.html
http://docs.oracle.com/javase/7/docs/technotes/guides/vm/server-class.html