“ java -server”の本当の違いおよび“ java -client&#8221 ;?

StackOverflow https://stackoverflow.com/questions/198577

  •  10-07-2019
  •  | 
  •  

質問

" java -server"の間に実際の違いはありますか? " java -client&quot ;?

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

  

"-サーバーの起動は遅くなりますが、速く実行する必要があります"。

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

役に立ちましたか?

解決

これは、実際には HotSpot およびデフォルトの option値 Java HotSpot VMオプション)。クライアントとサーバーの構成が異なります。

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

  

JDKには、2種類のVMが含まれています。クライアント側の提供と、サーバーアプリケーション用に調整された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 が指摘している in 64ビットバージョンのJDKでは、 -client オプションが長年無視されるというコメント
Windows java コマンド

-client
  

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

他のヒント

Javaの古いバージョンで最も目立つ直接的な違いは、 -server アプリケーションではなく、 -client に割り当てられたメモリです。たとえば、私の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"

so -server を使用すると、この java バージョンの場合、ほとんどのメモリ制限と初期割り当てがはるかに高くなります。

これらの値は、アーキテクチャ、オペレーティングシステム、jvmバージョンのさまざまな組み合わせによって変化する可能性があります。 jvmの最近のバージョンではフラグが削除され、サーバーとクライアントの多くの区別が削除されました。

jvisualvm を使用して、実行中の jvm の詳細をすべて表示できることも忘れないでください。これは、 JAVA_OPTS を設定するか、コマンドラインオプションを変更するスクリプトを使用するユーザーまたはモジュールがある場合に便利です。また、これにより、他の多くの統計とともに heap および permgen スペース使用量をリアルタイムで監視できます。

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

-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

サーバーシステムのより積極的な最適化は、アクションを実行しないことを理解しているため、ループを削除するようです!

リファレンス

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にどの程度当てはまるかわかりません。

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

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

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

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

リスト3.4。羊を数えます。

     

  揮発性ブール値のスリープ;   ...   while(!asleep)      countSomeSheep();

私の強調。 YMMV

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

サーバーモードのリンクです。残念ながら、クライアントモードについては言及していません。

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

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

2の間で起動時間に違いは見られませんでしたが、「-server」を使用してアプリケーションのパフォーマンスの向上を最小限に抑えました。 (Solarisサーバー、SunRaysを使用してアプリを実行する全員)。 1.5未満でした。

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

IIRC:

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

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

2つのスクリーンショットがあり、違いが非常によくわかりましたが、サーバーVMのみを実装する64ビットJVMがあるため再現できません。 (また、システムに32ビットバージョンをダウンロードして圧縮することもできません。)

サーバーとクライアントの両方のVMを使用してWindowsでコードを実行しようとすると、これはもう当てはまらないようです。両方で同じ生成モデルを取得するようです...

1.4から1.7(" 1.7.0_55")バージョンへの移行を行う場合、ここで観察したことは、クライアント&サーバーモード。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top