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

时间:2008-10-13 18:40:13

标签: java jvm jvm-hotspot

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

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

  

“ - 服务器启动速度较慢但应该运行得更快”。

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

10 个答案:

答案 0 :(得分:347)

这实际上与 HotSpot 和默认的选项值Java HotSpot VM Options)相关联,这些值在客户端和服务器配置之间有所不同。

来自白皮书的Chapter 2The Java HotSpot Performance Engine Architecture):

  

JDK包括两种VM:一种是客户端产品,另一种是针对服务器应用程序调整的VM。这两个解决方案共享Java HotSpot运行时环境代码库,但使用适合客户端和服务器的独特性能特征的不同编译器。这些差异包括编译内联策略和堆默认值。

     

虽然服务器和客户端虚拟机类似,但服务器虚拟机已经过专门调整,可以最大限度地提高峰值运行速度。它用于执行长时间运行的服务器应用程序,这些应用程序需要尽可能快的运行速度,而不是快速启动时间或更小的运行时内存占用。

     

客户端VM编译器用作旧版本JDK使用的Classic VM和实时(JIT)编译器的升级。客户端VM为应用程序和小程序提供了改进的运行时性能。 Java HotSpot客户端VM经过专门调整,可缩短应用程序启动时间和内存占用,使其特别适合客户端环境。通常,客户端系统更适合GUI。

所以真正的区别也在于编译器级别:

  

客户端VM编译器不会尝试执行服务器VM中编译器执行的许多更复杂的优化,但作为交换,它需要更少的时间来分析和编译一段代码。这意味着客户端VM可以更快地启动并且需要更小的内存占用。

     

服务器VM包含一个高级自适应编译器,它支持通过优化C ++编译器执行的许多相同类型的优化,以及传统编译器无法完成的一些优化,例如跨虚拟方法调用的积极内联。与静态编译器相比,这是一种竞争优势和性能优势。自适应优化技术的方法非常灵活,通常甚至优于高级静态分析和编译技术。

注意: jdk6 update 10 (请参阅Update Release Notes:Changes in 1.6.0_10)的发布试图改善启动时间,但由于与热点选项不同的原因,使用更小的内核进行不同的打包


G. Demecki指出in the comments在64位版本的JDK中,-client选项会被忽略多年。
Windows java command

-client
  

选择Java HotSpot客户端VM    64位功能的JDK当前忽略此选项,而是使用Java Hotspot Server VM

答案 1 :(得分:32)

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

答案 2 :(得分:28)

-client和-server系统是不同的二进制文件。它们本质上是两个不同的编译器(JIT),它们连接到同一个运行时系统。客户端系统最适合需要快速启动时间或占用空间小的应用程序,服务器系统最适合整体性能最重要的应用程序。通常,客户端系统更适合GUI等交互式应用程序

enter image description here

我们使用两个开关运行以下代码:

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

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

Reference

答案 3 :(得分:21)

Oracle的在线文档提供了Java SE 7的一些信息。

在Windows的java – the Java application launcher页面上,64位JDK中忽略-client选项:

  

选择Java HotSpot Client VM。具有64位功能的jdk当前忽略此选项,而是使用Java HotSpot Server VM。

然而(为了让事情变得有趣),在-server下说明:

  

选择Java HotSpot Server VM。在支持64位的jdk上,仅支持Java HotSpot Server VM,因此-server选项是隐式的。这可能会在将来的版本中发生变化。

Server-Class Machine Detection页面提供有关OS和架构选择的VM的信息。

我不知道这对JDK 6有多少。

答案 4 :(得分:15)

IIRC服务器VM在启动时执行更多热点优化,因此运行速度更快,但需要更长时间才能启动并使用更多内存。客户端VM推迟了大部分优化,以便更快地启动。

编辑添加:来自Sun的Here's some info,它不是非常具体,但会给你一些想法。

答案 5 :(得分:14)

来自Goetz - 实践中的Java并发:

  
      
  1. 调试提示:对于服务器应用程序,请务必在调用JVM时始终指定-server JVM命令行开关,即使对于   开发和测试。服务器JVM执行更多优化   比客户端JVM,例如从循环中提取变量   没有在循环中修改;可能似乎在   开发环境(客户端JVM)可以在部署中中断   环境(服务器JVM)。例如,如果我们“忘记”宣布   清单3.4中的变量aslele as volatile,服务器JVM可以   将测试从环路中提升(将其转换为无限循环),但是   客户端JVM不会。出现的无限循环   开发成本远远低于仅出现的开发成本   生产。
  2.         

    清单3.4。数羊。

         

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

我的重点。 YMMV

答案 6 :(得分:5)

IIRC,它涉及垃圾收集策略。理论上说,客户端和服务器在短期对象方面会有所不同,这对现代GC算法很重要。

服务器模式下的

Here is a link。唉,他们没有提到客户模式。

Here is a very thorough link一般关于GC;这是more basic article。不确定地址-server是否与-client相关,但这是相关材料。

在No Fluff Just Stuff,Ken Sipe和Glenn Vandenburg就这类事情进行了很好的讨论。

答案 7 :(得分:3)

我没有注意到2之间的启动时间有任何差异,但是使用“-server”(Solaris服务器,每个人都使用SunRays来运行应用程序),应用程序性能的改进非常小。那是在1.5以下。

答案 8 :(得分:1)

上次我看过这个,(并且不可否认它已经有一段时间了)我注意到的最大区别在于垃圾收集。

IIRC:

  • 服务器堆VM具有与客户端VM不同的代数,以及不同的垃圾收集算法。 这可能不再适用
  • 服务器VM将分配内存而不是将其释放到操作系统
  • 服务器VM将使用更复杂的优化算法,因此对优化有更大的时间和内存要求

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

我有一对屏幕截图显示差异非常好,但我无法重现,因为我有一个只实现服务器VM的64位JVM。 (而且我也不会为在我的系统上下载和纠缠32位版本而烦恼。)

这似乎不再是这种情况,尝试在服务器和客户端虚拟机的Windows上运行一些代码,我似乎得到了两者的相同代模型...

答案 9 :(得分: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

ThreadStackSize在1.7中更高,而在通过Open JDK论坛时,有讨论称1.7版本的帧大小稍高。 据信,根据您的应用程序行为,可以在运行时测量真正的差异