Answers:
这实际上与HotSpot和默认选项值(Java HotSpot VM Options)链接在一起,这些默认值在客户端和服务器配置之间有所不同。
从白皮书的第2章(Java HotSpot性能引擎体系结构)开始:
JDK包括两种VM:客户端产品和为服务器应用程序调整的VM。这两个解决方案共享Java HotSpot运行时环境代码库,但是使用不同的编译器,这些编译器适合于客户端和服务器的独特性能特性。这些差异包括编译内联策略和堆默认值。
尽管服务器VM和客户端VM相似,但已经对服务器VM进行了特殊调整,以最大程度地提高峰值运行速度。它用于执行长时间运行的服务器应用程序,这些应用程序需要比快速启动时间或较小的运行时内存占用更多的最快的运行速度。
客户端VM编译器可作为经典VM和早期JDK版本使用的即时(JIT)编译器的升级。Client VM为应用程序和小程序提供了改进的运行时性能。Java HotSpot客户端VM经过特别调整,以减少应用程序启动时间和内存占用,使其特别适合客户端环境。通常,客户端系统更适合GUI。
因此,真正的区别还在于编译器级别:
客户端VM编译器不会尝试执行服务器VM中由该编译器执行的许多更复杂的优化,但是作为交换,它需要更少的时间来分析和编译一段代码。这意味着客户端VM可以更快地启动,并且需要较小的内存空间。
Server VM包含一个高级自适应编译器,该编译器支持通过优化C ++编译器执行的许多相同类型的优化,以及一些传统编译器无法完成的优化,例如跨虚拟方法调用的主动内联。与静态编译器相比,这是一个竞争优势和性能优势。自适应优化技术的方法非常灵活,通常甚至优于高级静态分析和编译技术。
注意:jdk6 update 10 发行版(请参阅更新发行说明:1.6.0_10中的更改)试图缩短启动时间,但是出于与hotspot选项不同的原因,它与更小的内核打包在一起。
G. Demecki指出,在评论,在JDK的64位版本,该-client
选项是多年来忽视。
请参阅Windows java
命令:
-client
选择Java HotSpot客户端VM。
具有64位功能的JDK当前忽略此选项,而是使用Java Hotspot Server VM。
-client
选项多年来一直被忽略。
Java的较早版本中最明显的直接区别就是分配给-client
而不是-server
应用程序的内存。例如,在我的Linux系统上,我得到:
$ java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight = 20 {product}
uintx ErgoHeapSizeLimit = 0 {product}
uintx InitialHeapSize := 66328448 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 1063256064 {product}
uintx MaxPermSize = 67108864 {pd product}
uintx PermSize = 16777216 {pd product}
java version "1.6.0_24"
因为它默认为-server
,但是带有-client
选项我得到:
$ java -client -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight = 20 {product}
uintx ErgoHeapSizeLimit = 0 {product}
uintx InitialHeapSize := 16777216 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 268435456 {product}
uintx MaxPermSize = 67108864 {pd product}
uintx PermSize = 12582912 {pd product}
java version "1.6.0_24"
因此,-server
对于此java
版本,大多数内存限制和初始分配都更高。
但是,对于架构,操作系统和jvm版本的不同组合,这些值可以更改。jvm的最新版本已删除标记,并删除了服务器和客户端之间的许多区别。
别忘了,你可以看到一个正在运行的所有细节jvm
使用jvisualvm
。如果您拥有设置JAVA_OPTS
或使用更改命令行选项的脚本的用户或模块,这将非常有用。这还使您可以实时监视堆和permgen空间使用情况以及许多其他统计信息。
-client和-server系统是不同的二进制文件。它们本质上是连接到同一运行时系统的两个不同的编译器(JIT)。对于需要快速启动时间或较小占用空间的应用程序,客户端系统是最佳选择;对于整体性能最为重要的应用程序,服务器系统是最佳选择。通常,客户端系统更适合于GUI等交互式应用程序
我们使用两个开关运行以下代码:
package com.blogspot.sdoulger;
public class LoopTest {
public LoopTest() {
super();
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
spendTime();
long end = System.currentTimeMillis();
System.out.println("Time spent: "+ (end-start));
LoopTest loopTest = new LoopTest();
}
private static void spendTime() {
for (int i =500000000;i>0;i--) {
}
}
}
注意:该代码仅被编译一次!两次运行中的类都相同!
使用-client:
java.exe -client -classpath C:\ mywork \ classes com.blogspot.sdoulger.LoopTest
花费的时间:766
使用-server:
java.exe -server -classpath C:\ mywork \ classes com.blogspot.sdoulger.LoopTest
花费的时间:0
似乎是对服务器系统进行了更为积极的优化,因此删除了循环,因为它知道它不执行任何操作!
Oracle的在线文档提供了有关Java SE 7的一些信息。
在Windows 的Java – Java应用程序启动器页面上,该-client
选项在64位JDK中被忽略:
选择Java HotSpot客户端VM。具有64位功能的jdk当前会忽略此选项,而是使用Java HotSpot Server VM。
但是(为了使事情变得有趣),在-server
其下指出:
选择Java HotSpot服务器VM。在支持64位的jdk上,仅支持Java HotSpot Server VM,因此-server选项是隐式的。这可能会在将来的版本中更改。
“ 服务器级计算机检测”页面提供有关操作系统和体系结构选择了哪个VM的信息。
我不知道有多少适用于JDK 6。
从Goetz-实践中的Java并发性:
- 调试技巧:对于服务器应用程序,请确保
-server
在调用JVM时始终指定JVM命令行开关,即使是用于开发和测试也是如此。服务器JVM比客户端JVM执行更多的优化,例如从循环中提升未在循环中修改的变量。在开发环境(客户端JVM)中似乎有效的代码可能会在部署环境(服务器JVM)中中断。例如,如果我们在清单3.4中“忘记了”将变量sleep声明为volatile,则服务器JVM可以将测试退出循环(将其变为无限循环),而客户端JVM则不能。在开发中显示的无限循环比仅在生产中显示的无限循环要便宜得多。清单3.4。数羊。
volatile boolean asleep; ... while (!asleep) countSomeSheep();
我的重点。青年汽车
IIRC服务器VM在启动时会进行更多的热点优化,因此运行速度更快,但是启动时间稍长,并且使用更多的内存。客户端VM推迟了大多数优化,以加快启动速度。
我没有注意到两者之间的启动时间有什么不同,但是使用“ -server”(Solaris服务器,每个人都使用SunRays运行该应用程序)在应用程序性能方面取得了非常小的改进。低于1.5。
上次我看了一下(当然,回想起是前一段时间),我注意到的最大区别是垃圾收集。
IIRC:
如果可以使用jvisualvm工具比较两个Java VM,一个客户端,一个服务器,则应该看到垃圾回收的频率和效果以及世代数的差异。
我有一对截屏,它们之间的差异非常好,但是我无法重现,因为我有一个仅实现服务器VM的64位JVM。(而且我也不必费心下载和纠缠系统中的32位版本。)
似乎已经不再是这种情况了,尝试在带有服务器和客户端VM的Windows上运行一些代码后,我似乎为两者获得了相同的生成模型...
从1.4版本过渡到1.7(“ 1.7.0_55”)版本时。我们在这里观察到的是,在客户端和服务器模式下,分配给heapsize | permsize | ThreadStackSize参数的默认值没有这种差异。
顺便说一下,(http://www.oracle.com/technetwork/java/ergo5-140223.html)。这是从上面的链接摘录的片段。
initial heap size of 1/64 of physical memory up to 1Gbyte
maximum heap size of ¼ of physical memory up to 1Gbyte
1.7中的ThreadStackSize更高,在通过Open JDK论坛时,有讨论说1.7版的框架大小更高。据信,根据您的应用程序的行为,可以在运行时测量实际差异。