"java -server"和"java -client"之间有什么实际的区别吗?我在Sun的网站上找到的只是一个模糊的" - 服务器启动较慢但应该运行得更快".有什么真正的区别?(目前使用JDK 1.6.0_07.)
这实际上与HotSpot和默认选项值(Java HotSpot VM Options)相关联)在客户端和服务器配置之间有所不同.
从白皮书的第2章(Java HotSpot性能引擎架构):
JDK包括两种类型的VM - 客户端产品和针对服务器应用程序调整的VM.这两个解决方案共享Java HotSpot运行时环境代码库,但使用适合客户端和服务器的独特性能特征的不同编译器.这些差异包括编译内联策略和堆默认值.
尽管服务器和客户端虚拟机类似,但服务器虚拟机已经过专门调整,以最大限度地提高峰值运行速度.它用于执行长时间运行的服务器应用程序,这些应用程序需要尽可能快的运行速度,而不是快速启动时间或较小的运行时内存占用.
客户端VM编译器用作经典VM和先前版本的JDK使用的实时(JIT)编译器的升级.客户端VM为应用程序和小程序提供了改进的运行时性能.Java HotSpot客户端VM经过专门调整,可缩短应用程序启动时间和内存占用,使其特别适合客户端环境.通常,客户端系统更适合GUI.
所以真正的区别也在于编译器级别:
客户端VM编译器不会尝试执行服务器VM中编译器执行的许多更复杂的优化,但作为交换,它需要更少的时间来分析和编译一段代码.这意味着客户端VM可以更快地启动并且需要更小的内存占用.
Server VM包含一个高级自适应编译器,它支持通过优化C++编译器执行的许多相同类型的优化,以及传统编译器无法完成的一些优化,例如跨虚拟方法调用的积极内联.与静态编译器相比,这是一种竞争优势和性能优势.自适应优化技术的方法非常灵活,通常甚至优于高级静态分析和编译技术.
注意:jdk6 update 10的发布(参见更新发行说明:1.6.0_10中的更改)试图改善启动时间,但由于与热点选项不同的原因,使用更小的内核进行不同的打包.
G. Demecki指出,在评论,在JDK的64位版本,该-client
选项是多年来忽视.
请参阅Windows java
命令:
-client
选择Java HotSpot客户端VM.
支持64位的JDK当前忽略此选项,而是使用Java Hotspot Server VM.
旧版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空间使用情况以及许多其他统计信息.
我刚才注意到的一个区别是,在"客户端"模式下,似乎JVM实际上将一些未使用的内存返回给操作系统 - 而使用"服务器"模式,一旦JVM抓取内存,它就不会给它背部.这就是它在Solaris上用Java6出现的方式(使用prstat -Z来查看分配给进程的内存量).
-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的一些信息.
在Java( Windows 的Java应用程序启动器页面)上,该-client
选项在64位JDK中被忽略:
选择Java HotSpot Client VM.具有64位功能的jdk当前忽略此选项,而是使用Java HotSpot Server VM.
然而(为了让事情变得有趣),在-server
它下面说:
选择Java HotSpot Server VM.在支持64位的jdk上,仅支持Java HotSpot Server VM,因此-server选项是隐式的.这可能会在将来的版本中发生变化.
" 服务器级机器检测"页面提供有关OS和体系结构选择的VM的信息.
我不知道这对JDK 6有多大帮助.
IIRC服务器VM在启动时执行更多热点优化,因此运行速度更快,但需要更长时间才能启动并使用更多内存.客户端VM推迟大部分优化以允许更快的启动.
编辑添加:这是来自Sun 的一些信息,它不是非常具体,但会给你一些想法.
来自Goetz - 实践中的Java并发:
调试提示:对于服务器应用程序,请确保在调用JVM时始终指定-server JVM命令行开关,即使是用于开发和测试.服务器JVM执行比客户端JVM更多的优化,例如从循环中提取变量而不在循环中修改; 可能看起来在开发环境(客户端JVM)中工作的代码可能在部署环境(服务器JVM)中中断.例如,如果我们"遗忘"在清单3.4中将变量声明为volatile,则服务器JVM可以将测试从循环中提升(将其转换为无限循环),但客户端JVM则不会.在开发过程中出现的无限循环远远低于仅在生产中出现的循环.
清单3.4.算羊.
-server
我的重点.因人而异
IIRC,它涉及垃圾收集策略.理论上说,客户端和服务器在短期对象方面会有所不同,这对现代GC算法很重要.
这是服务器模式的链接.唉,他们没有提到客户端模式.
以下是 GC的一个非常全面的链接 ; 这是一篇更基础的文章.不确定是否地址-server vs -client,但这是相关材料.
在No Fluff Just Stuff,Ken Sipe和Glenn Vandenburg都在就这类事情进行了很好的讨论.