「java -server」と「java -client」の本当の違いは?


394

「java -server」と「java -client」の間に実際の実用的な違いはありますか?

Sunのサイトで見つけられるのは漠然

「-serverの起動は遅くなりますが、実行は速くなります」。

実際の違いは何ですか?(現在、JDK 1.6.0_07を使用しています。)

回答:


368

これは実際にはHotSpotとリンクされており、デフォルトのオプション値Java HotSpot VM Options)はクライアントとサーバーの設定で異なります。

第2章ホワイトペーパー(のは、Java HotSpotパフォーマンスエンジンアーキテクチャ):

JDKには、クライアント側のオファリングとサーバーアプリケーション用に調整されたVMの2種類のVMが含まれています。これら2つのソリューションは、Java HotSpotランタイム環境のコードベースを共有しますが、クライアントとサーバーの明確に固有のパフォーマンス特性に適した異なるコンパイラーを使用します。これらの違いには、コンパイルのインラインポリシーとヒープのデフォルトが含まれます。

サーバーVMとクライアントVMは似ていますが、サーバーVMはピーク動作速度を最大化するように特別に調整されています。これは、高速な起動時間や実行時のメモリフットプリントよりも高速で可能な最高速の動作速度を必要とする、長時間実行されるサーバーアプリケーションを実行するためのものです。

クライアントVMコンパイラは、クラシックVMと、以前のバージョンのJDKで使用されていたジャストインタイム(JIT)コンパイラの両方のアップグレードとして機能します。クライアントVMは、アプリケーションとアプレットの実行時パフォーマンスを向上させます。Java HotSpot Client VMは、アプリケーションの起動時間とメモリフットプリントを削減するように特別に調整されており、クライアント環境に特に適しています。一般に、クライアントシステムはGUIに適しています。

したがって、実際の違いはコンパイラレベルにもあります。

クライアントVMコンパイラは、サーバーVMのコンパイラによって実行されるより複雑な最適化の多くを実行しようとはしませんが、その代わりに、コードの一部を分析してコンパイルするために必要な時間を短縮できます。つまり、クライアントVMはより速く起動でき、必要なメモリフットプリントが小さくなります。

サーバーVMには、C ++コンパイラの最適化によって実行される同じタイプの最適化の多くをサポートする高度な適応型コンパイラと、仮想メソッド呼び出し全体の積極的なインライン化など、従来のコンパイラでは実行できないいくつかの最適化が含まれています。これは、静的コンパイラよりも競争力があり、パフォーマンスが優れている点です。適応最適化テクノロジーは、そのアプローチが非常に柔軟であり、通常、高度な静的分析およびコンパイル技術よりも優れています。

注:jdk6 update 10のリリースアップデートリリースノート:1.6.0_10での変更を参照)は起動時間を改善しようとしましたが、ホットスポットオプションとは異なる理由で、はるかに小さいカーネルで異なる方法でパッケージ化されました。


G. Demecki は、コメントで指摘しているように、64ビットバージョンのJDKでは、この-clientオプションは長年にわたって無視されます。Windows コマンドを
参照してください:java

-client

Java HotSpot Client VMを選択します。
64ビット対応のJDKは現在このオプションを無視し、代わりにJava Hotspot Server VMを使用しています


7
jdk6 update 10以降には、ランタイムライブラリをメモリに保持するバックグラウンドプロセスがあり、すべてをオンデマンドでページングする必要がない場合よりも、新しいプロセスの起動がはるかに高速になります。
するThorbjörnRavnアンデルセン

1
クライアントのvmも積極的にインライン化したと考えました。
–ThorbjørnRavn Andersen 2010

1
この答え更新されるべきだと思います。JDKの64ビットバージョンでは、この-clientオプションは何年もの間無視されます。
G.デメッキ

@ G.Demecki確かに:このオプションが廃止されたか無視されていることを説明するリンクはありますか?
VonC 2016年

1
承知しました。これは、Java 7 for Windowsのドキュメントです。そして驚いたことに、同様の情報がJava 6のドキュメントにもあります
G.デメッキ

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 ]
バジルムーサ2016年

4
これが私が答えを出した理由です。それは値ではなく、いつでも、誰でも特定のjvmバージョンの答えを見つけられるようにすることです。
マークブース

33

-clientシステムと-serverシステムは異なるバイナリです。これらは基本的に、同じランタイムシステムに接続する2つの異なるコンパイラ(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

私が気付いた1つの違いは、「クライアント」モードでは、JVMが実際に未使用のメモリをオペレーティングシステムに戻すように見えるのに対し、「サーバー」モードでは、JVMがメモリを取得すると、メモリが提供されないことです。バック。とにかく、Java6を搭載したSolarisでそれがどのように表示されるか(prstat -Zプロセスに割り当てられたメモリの量を確認するために使用)。


22

Oracleのオンラインドキュメントには、Java SE 7に関する情報が記載されています。

のjava - Javaアプリケーション起動用のWindows用のページ、-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オプションは暗黙的です。これは将来のリリースで変更される可能性があります。

サーバークラスマシンの検出のページは、VMがOSやアーキテクチャによって選択されている情報を提供します。

これがJDK 6にどの程度当てはまるのかわかりません。


2
おかげで、JDK7にclient / jvm.dllが表示されないのはなぜだろうと思っていました
Archimedes Trajano 14

16

Goetzから-実際のJava同時実行性:

  1. デバッグのヒント:サーバーアプリケーションの-server場合、開発やテストあっても、JVMを呼び出すときは常にJVMコマンドラインスイッチを指定してください。サーバーJVMは、クライアントJVMよりも多くの最適化を実行します。たとえば、ループ内で変更されない変数をループから引き上げます。開発環境(クライアントJVM)で動作するように見えるコードは、デプロイメント環境(サーバーJVM)で機能しなくなる可能性があります。たとえば、リスト3.4で変数asleepをvolatileとして宣言することを「忘れた」場合、サーバーJVMはテストをループから引き上げ(無限ループに変換)できましたが、クライアントJVMはそうしませんでした。開発で現れる無限ループは、本番でのみ現れるループよりもはるかに低コストです。

リスト3.4 羊を数える。

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

私の強調。YMMV


15

IIRCサーバーVMは起動時により多くのホットスポット最適化を実行するため、実行は速くなりますが、起動に少し時間がかかり、より多くのメモリを使用します。クライアントVMは、起動の高速化を可能にするために、最適化のほとんどを延期します。

追加して編集:これはSunからの情報です。あまり具体的ではありませんが、いくつかのアイデアを提供します。


5

IIRC、それはガベージコレクション戦略を含みます。理論では、クライアントとサーバーは、存続期間の短いオブジェクトの点で異なります。これは、最新のGCアルゴリズムにとって重要です。

これはサーバーモードのリンクです。悲しいかな、彼らはクライアントモードについて言及していません。

一般的なGCに関する非常に詳細なリンク次に示します。これはより基本的な記事です。-serverと-clientのどちらのアドレスかはわかりませんが、これは関連資料です。

No Fluff Just Stuffでは、Ken SipeとGlenn Vandenburgがこの種のことについて素晴らしい講演を行っています。


3

2つの起動時間の違いに気づきませんでしたが、 "-server"(Solarisサーバー、アプリを実行するためにSunRaysを使用しているすべてのユーザー)を使用して、アプリケーションのパフォーマンスの改善を最小限に抑えました。それは1.5未満でした。


6
プログラムの動作に依存します。同じことを繰り返し行う一部のプロセッサ集中型アプリケーションでは、-serverによる大幅(最大10倍の)改善に気づきました。
Dan Dyer、

1
ダン、これへの言及はありますか?さらに調査したいのですが。
するThorbjörnRavnアンデルセン

1
サーバーVMでのSunflowの実行は、クライアントよりもはるかに高速です。sunflow.sourceforge.net
ジョン

1

前回これを見たとき(確かにしばらく前だったと思います)、気づいた最大の違いはガベージコレクションにありました。

ちゃんと覚えたら:

  • サーバーヒープVMの世代数はクライアントVMとは異なり、ガベージコレクションアルゴリズムも異なります。これはもう本当ではないかもしれません
  • サーバーVMはメモリを割り当て、OSに解放しません
  • サーバーVMはより高度な最適化アルゴリズムを使用するため、最適化に必要な時間とメモリの要件が大きくなります。

jvisualvmツールを使用して、2つのJava VM、1つのクライアント、1つのサーバーを比較できる場合は、ガベージコレクションの頻度と効果、および世代数に違いがあるはずです。

違いを非常によく示すスクリーンショットのペアがありましたが、サーバー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

ThreadStackSizeは1.7で高くなっていますが、Open JDKフォーラムを通過しているときに、フレームサイズが1.7バージョンでいくらか高くなっているという議論があります。実際の違いは、アプリケーションの動作に基づいて実行時に測定できる可能性があると考えられています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.