web-dev-qa-db-ja.com

"Java-server"と "Java -client"の本当の違いは?

"Java-server"と "Java -client"の間に実際的な違いはありますか?

私がSunのサイトで見つけることができるのはあいまいなだけです

#〜msgstr "-serverの起動は遅くなりますが高速になるはずです"#:。

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

372
Paul Tomblin

これは本当にHotSpotおよびデフォルトのオプション値Java HotSpot VMオプション )クライアントとサーバーの設定によって異なります。

ホワイトペーパーの 第2章Java HotSpot Performance Engineアーキテクチャ )から:

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

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

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

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

Client VMコンパイラは、Server VM内でコンパイラによって実行されるより複雑な最適化の多くを実行しようとはしませんが、その代わりに、コードの解析とコンパイルにかかる時間が短縮されます。これは、Client VMの起動が速くなり、必要なメモリ容量が少なくて済むことを意味します。

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

注:jdk6 update 10pdate Release Notes:1.6.0_10での変更点 を参照)のリリースでは、起動時間を短縮しようとしましたが、理由が異なりますホットスポットオプションよりも、はるかに小さいカーネルで異なってパッケージされています。


G。Demecki 指摘した コメント内 64ビット版のJDKでは、-clientオプションは長年無視されていました。
Windows Javaコマンド を参照してください。

-client

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

347
VonC

古いバージョンの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を設定したり、コマンドラインオプションを変更するスクリプトを使用するユーザーやモジュールを持っている場合に便利です。これにより、heapおよびpermgenスペース使用量を他の多くの統計と共にリアルタイムで監視することもできます。

87
Mark Booth

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

32
prule

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

注:コードは1回だけコンパイルされます。両方の実行でクラスは同じです。

-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

サーバーシステムがより積極的に最適化されれば、何のアクションも実行しないことが理解されるので、ループを削除するようです。

参考

28
Premraj

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

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

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

これがどれほどJDK 6に当てはまるのか私は知りません。

21
pharsicle

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

追加するための編集: これはSunからの情報 です。具体的な情報ではありませんが、いくつかのアイデアが得られます。

15
Mike Akers

Goetzから - 実践におけるJavaの並行性:

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

リスト3.4羊を数える。

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

私の強調YMMV

14
Adam

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

これはリンクです サーバーモードで。ああ、彼らはクライアントモードについては触れていない。

これは非常に徹底的なリンクです 一般にGCについて。これは より基本的な記事 です。アドレス-serverと-clientのどちらが正しいかわからないが、これは適切な資料です。

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

5
Michael Easter

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

3
Brian Knoblauch

前回これを見たとき(そして明らかにそれはしばらく前のことでした)、私が気付いた最大の違いはガベージコレクションにありました。

IIRC:

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

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

私は違いを本当によく示している一対のスクリーンショットを持っていました、しかし私は私がサーバーVMだけを実行する64ビットJVMを持っているので再現できません。 (そして私のシステムでも32ビット版をダウンロードして悩ますのは面倒なことではない。)

これはもう当てはまらないようです。サーバーVMとクライアントVMの両方でWindows上でいくつかのコードを実行しようとしましたが、どちらも同じ世代モデルを使用しているようです...

1
brice

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バージョンではフレームサイズがやや大きいという議論があります。実際の違いは、アプリケーションの動作に基づいて実行時に測定できる可能性があると考えられています。

1
Nuwan Arambage