“ java -server”和“ java -client”之间的真正区别?


394

“ java -server”和“ java -client”之间是否有实际的实际区别?

我在Sun网站上所能找到的一切都是模糊的

“ -server启动速度较慢,但​​应运行得更快”。

真正的区别是什么?(当前使用JDK 1.6.0_07。)

Answers:


368

这实际上与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


7
jdk6 update 10及更高版本具有一个后台进程,该进程将运行时库保存在内存中,从而使新进程的启动要快得多,而不必按需分页。
托尔比约恩Ravn的安徒生

1
以为客户端虚拟机也积极内联了,哦。
托尔比约恩Ravn的安徒生

1
我认为这个答案应该更新。因为在JDK的64位版本上,此-client选项多年来一直被忽略。
G. Demecki

@ G.Demecki当然:您是否有链接记录此选项已过时或被忽略了?
VonC

1
当然。这是Java 7 for Windows的一些文档资料。令人惊讶的是,在Java 6 文档中也可以找到类似的信息。
G. Demecki

90

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空间使用情况以及许多其他统计信息。


2
它在CentOS 7 [Java(TM)SE运行时环境(内部版本1.7.0_79-b15)Java HotSpot(TM)64位服务器VM ]
Basil Musa

4
这就是为什么我提供了答案。这与价值无关,而是与使任何人都能随时找到其特定jvm版本的答案有关。
Mark Booth's

33

-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

似乎是对服务器系统进行了更为积极的优化,因此删除了循环,因为它知道它不执行任何操作!

参考


33

我刚刚注意到的一个区别是,在“客户端”模式下,似乎JVM实际上将一些未使用的内存返回给操作系统,而在“服务器”模式下,一旦JVM捕获了内存,它就不会给它。背部。这就是它在带有Java6的Solaris上的显示方式(prstat -Z用来查看分配给进程的内存量)。


22

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。


2
谢谢,我想知道为什么我在JDK7上看不到client / jvm.dll
Archimedes Trajano 2014年

16

从Goetz-实践中的Java并发性:

  1. 调试技巧:对于服务器应用程序,请确保-server在调用JVM时始终指定JVM命令行开关,即使是用于开发和测试也是如此。服务器JVM比客户端JVM执行更多的优化,例如从循环中提升未在循环中修改的变量。在开发环境(客户端JVM)中似乎有效的代码可能会在部署环境(服务器JVM)中中断。例如,如果我们在清单3.4中“忘记了”将变量sleep声明为volatile,则服务器JVM可以将测试退出循环(将其变为无限循环),而客户端JVM则不能。在开发中显示的无限循环比仅在生产中显示的无限循环要便宜得多。

清单3.4。数羊。

volatile boolean asleep; ... while (!asleep) countSomeSheep();

我的重点。青年汽车


15

IIRC服务器VM在启动时会进行更多的热点优化,因此运行速度更快,但是启动时间稍长,并且使用更多的内存。客户端VM推迟了大多数优化,以加快启动速度。

编辑添加:这是 Sun 的一些信息,虽然不是很具体,但是会给您一些想法。


5

IIRC,它涉及垃圾收集策略。从理论上讲,就短期对象而言,客户端和服务器将有所不同,这对于现代GC算法很重要。

这是服务器模式下的链接。,他们没有提到客户端模式。

一般来说,这是关于GC 的非常详尽的链接;这是更基础的文章。不知道地址-server vs -client是不是相关材料。

在No Fluff Just Stuff上,肯·斯佩(Ken Sipe)和格伦·范登堡(Glenn Vandenburg)都在这类事情上进行了精彩的演讲。


3

我没有注意到两者之间的启动时间有什么不同,但是使用“ -server”(Solaris服务器,每个人都使用SunRays运行该应用程序)在应用程序性能方面取得了非常小的改进。低于1.5。


6
取决于您的程序在做什么。对于某些重复执行相同操作的处理器密集型应用程序,我注意到-server进行了巨大的改进(最多10倍)。
丹·代尔

1
丹,您对此有参考吗?我想进一步调查。
托尔比约恩Ravn的安徒生

1
在服务器VM上运行Sunflow比客户端快得多。sunflow.sourceforge.net
约翰,2:

1

上次我看了一下(当然,回想起是前一段时间),我注意到的最大区别是垃圾收集。

IIRC:

  • 服务器堆VM与客户端VM具有不同的世代数,并且具有不同的垃圾收集算法。这可能不再是真的
  • 服务器虚拟机将分配内存,而不将其释放给操作系统
  • 服务器虚拟机将使用更复杂的优化算法,因此需要更多的时间和内存来进行优化

如果可以使用jvisualvm工具比较两个Java VM,一个客户端,一个服务器,则应该看到垃圾回收的频率和效果以及世代数的差异。

我有一对截屏,它们之间的差异非常好,但是我无法重现,因为我有一个仅实现服务器VM的64位JVM。(而且我也不必费心下载和纠缠系统中的32位版本。)

似乎已经不再是这种情况了,尝试在带有服务器和客户端VM的Windows上运行一些代码后,我似乎为两者获得了相同的生成模型...


1

从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版的框架大小更高。据信,根据您的应用程序的行为,可以在运行时测量实际差异。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.