“java -server”和“;而“java -client”呢?

“java -server”和“java -client”之间有什么实际的区别吗?

我在孙的网站上只能找到一个模糊的

-服务器启动较慢,但应该运行得更快。

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

259016 次浏览

我没有注意到两者在启动时间上有任何不同,但使用“-server”(Solaris服务器,每个人都使用SunRays来运行应用程序)时,应用程序性能的提高非常小。低于1.5。

IIRC服务器虚拟机在启动时做了更多的热点优化,所以它运行得更快,但启动时间稍长,占用更多内存。客户端VM推迟了大部分优化,以允许更快的启动。

编辑添加:这里有一些信息来自Sun,它不是很具体,但会给你一些想法。

IIRC,它涉及到垃圾收集策略。其理论是客户机和服务器在短寿命对象方面是不同的,这对现代GC算法很重要。

这是一个链接在服务器模式。唉,他们没有提到客户端模式。

这里有一个非常完整的链接在GC一般;这是一个更基础的文章。不确定地址-服务器和-客户端,但这是相关的材料。

在No Fluff Just Stuff, Ken Sipe和Glenn Vandenburg都在这方面做了很棒的演讲。

这实际上链接到热点和默认的选项值 (Java热点虚拟机选项),它们在客户端和服务器配置之间是不同的。

从白皮书的第二章 (Java HotSpot性能引擎架构):

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

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

Client VM编译器可以作为经典VM和JDK以前版本使用的即时(JIT)编译器的升级。Client VM为应用程序和小程序提供了改进的运行时性能。Java HotSpot Client VM经过了特别的调优,以减少应用程序启动时间和内存占用,使其特别适合客户机环境。一般来说,客户端系统更适合gui。

所以真正的区别还在于编译器层面:

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

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

注意:Jdk6更新10的发布(参见更新发布说明:1.6.0_10的更改)试图改善启动时间,但原因与热点选项不同,它被打包在一个小得多的内核中。


g . Demecki指出在评论中在64位版本的JDK中,-client选项多年来一直被忽略。
看到Windows java命令: < / p >

-client

选择Java HotSpot Client虚拟机。
支持64位的JDK目前忽略了这个选项,而是使用Java Hotspot Server VM


2022: Holger引用的评论中的JavaSE6 /服务器类机器检测,添加:

只有在32位Windows系统上,-client被无条件地选择。
其他系统检查机器是否为“服务器类”,当至少有2个核心和至少2GiB的内存时,这是满足的

这就解释了为什么现在几乎所有东西都在使用-server。即使是你能找到的最便宜的电脑,也是“服务器级”机器。Sun/Oracle 64版本甚至没有附带客户端JVM。

我刚刚注意到的一个不同之处在于,在“客户端”模式下,JVM似乎会将一些未使用的内存归还给操作系统,而在“服务器”模式下,一旦JVM获取了内存,它就不会将其归还。这就是它在Solaris和Java6上的表现(使用prstat -Z来查看分配给进程的内存量)。

在旧版本的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的最新版本已经删除了标志,并删除了服务器和客户端之间的许多区别。

还要记住,你可以使用jvisualvm查看正在运行的jvm的所有细节。如果你的用户或模块设置了JAVA_OPTS,或者使用了修改命令行选项的脚本,这是很有用的。这也可以让你实时监控permgen空间使用情况以及许多其他统计数据。

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

在Windows的java - java应用程序启动器页面上,在64位JDK中-client选项会被忽略:

选择“Java HotSpot Client”虚拟机。支持64位的jdk目前忽略了这个选项,而是使用Java HotSpot Server VM。

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

选择Java热点服务器虚拟机。在支持64位的jdk上,只支持Java HotSpot Server VM,因此-server选项是隐式的。这可能会在未来的版本中更改。

服务器类机器检测页面根据操作系统和体系结构给出了选择哪个虚拟机的信息。

我不知道这其中有多少适用于JDK 6。

上次我看了这个,(不可否认,这是一段时间以前了)我注意到的最大区别是在垃圾收集方面。

IIRC:

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

如果你可以比较两个java虚拟机,一个客户端,一个服务器使用jvisualvm工具,你应该看到垃圾收集的频率和效果,以及在代的数量上的差异。

我有一对屏幕截图,很好地显示了差异,但我不能再现,因为我有一个64位JVM,它只实现了服务器VM。(我也懒得在我的系统上下载和争论32位版本。)

这种情况似乎不再是这样了,尝试在服务器和客户端vm的windows上运行一些代码,我似乎得到了相同的生成模型…

当从1.4版本迁移到1.7版本(“1.7.0_55”)时。我们在这里观察到的是,在client &中分配给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版本中更高,而在开放JDK论坛中,有讨论指出1.7版本的帧大小略高。 相信在运行时可以根据应用程序的行为

来衡量真正的差异

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--) {
}
}
}

注意:代码只编译了一次!这两个运行中的类是相同的!

< p > 客户端: < br > C:\mywork\classes com.blogspot.sdoulger.LoopTest
时间:766

< p > -服务器: < br > java.exe -server -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
时间花费:0

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

Reference .

来自Goetz - Java并发实践:

    调试提示:对于服务器应用程序,请确保在调用JVM时始终指定-server JVM命令行开关,甚至对于 开发和测试。服务器JVM执行更多优化 而不是客户端JVM,比如从循环中提升变量 未在循环中修改;中可能工作的代码 开发环境(客户机JVM)可能会中断部署 环境(服务器JVM)。例如,如果我们“忘记”申报 清单3.4中的变量休眠为volatile,服务器JVM可以使用 将测试从循环中提升出来(将其变为无限循环),但是 客户端JVM不会。一个无限循环出现在 开发的成本远远低于只在 李生产。< / >

清单3.4。数羊。

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

我的重点。YMMV