「java -server」と「java -client」の間に実質的な実際の違いはありますか?
Sunのサイトで見つけられるのは漠然としたものだけです
「-サーバーの起動は遅くなりますが、より速く実行されるはずです」。
本当の違いは何ですか?(現在JDK 1.6.0_07を使用しています。)
「java -server」と「java -client」の間に実質的な実際の違いはありますか?
Sunのサイトで見つけられるのは漠然としたものだけです
「-サーバーの起動は遅くなりますが、より速く実行されるはずです」。
本当の違いは何ですか?(現在JDK 1.6.0_07を使用しています。)
これは、実際にはHotSpotと、クライアントとサーバーの構成間で異なるデフォルトのオプション値(Java HotSpot VMオプション)にリンクされています。
ホワイトペーパー(Java HotSpotパフォーマンスエンジンアーキテクチャ)の第2章から:
JDKには、クライアント側のオファリングとサーバーアプリケーション用に調整されたVMの2種類のVMが含まれています。これらの2つのソリューションは、Java HotSpotランタイム環境のコードベースを共有しますが、クライアントとサーバーの明確に固有のパフォーマンス特性に適した異なるコンパイラーを使用します。これらの違いには、コンパイルのインライン化ポリシーとヒープのデフォルトが含まれます。
サーバーVMとクライアントVMは似ていますが、サーバーVMは、ピーク動作速度を最大化するように特別に調整されています。これは、起動時間が短い、または実行時のメモリフットプリントが小さいよりも、可能な限り最速の動作速度を必要とする、長時間実行されるサーバーアプリケーションを実行することを目的としています。
クライアントVMコンパイラは、クラシックVMと以前のバージョンのJDKで使用されていたジャストインタイム(JIT)コンパイラの両方のアップグレードとして機能します。クライアントVMは、アプリケーションとアプレットの実行時パフォーマンスを向上させます。Java HotSpotクライアントVMは、アプリケーションの起動時間とメモリフットプリントを削減するように特別に調整されているため、クライアント環境に特に適しています。一般に、クライアントシステムはGUIに適しています。
したがって、実際の違いはコンパイラレベルにもあります。
クライアントVMコンパイラは、サーバーVMでコンパイラによって実行されるより複雑な最適化の多くを実行しようとはしませんが、代わりに、コードの一部を分析およびコンパイルするために必要な時間が短縮されます。これは、クライアントVMの起動が速くなり、必要なメモリフットプリントが小さくなることを意味します。
サーバーVMには、C ++コンパイラーの最適化によって実行される同じタイプの最適化の多くと、仮想メソッド呼び出し間の積極的なインライン化など、従来のコンパイラーでは実行できないいくつかの最適化をサポートする高度な適応コンパイラーが含まれています。これは、静的コンパイラよりも競争力があり、パフォーマンスが優れています。適応最適化テクノロジーは、そのアプローチにおいて非常に柔軟性があり、通常、高度な静的分析およびコンパイル技術よりも優れています。
注:jdk6アップデート10のリリース(アップデートリリースノート:1.6.0_10での変更を参照)は起動時間を改善しようとしましたが、ホットスポットオプションとは異なる理由で、はるかに小さいカーネルで異なる方法でパッケージ化されました。
G. Demeckiはコメントの中で、64ビットバージョンのJDKでは、この-client
オプションは何年もの間無視されていると指摘しています。Windowsコマンド
を参照してください:java
-client
JavaHotSpotクライアントVMを選択します。
64ビット対応のJDKは現在、このオプションを無視し、代わりにJava HotspotServerVMを使用します。
2022:Holgerは、コメントでJavaSE6 /サーバークラスのマシン検出を参照し、次のように追加しています。
32ビットWindowsシステムでのみ、
-client
無条件に選択されました。
他のシステムは、マシンが「サーバークラス」であるかどうかをチェックしました。これは、少なくとも2つのコアと少なくとも2GiBのメモリがある場合に満たされました。
-server
これは、ほとんどすべてが今かなり長い間使用されている理由を説明しています。あなたが見つけることができる最も安いコンピュータでさえ、「サーバークラス」のマシンです。Sun / Oracle 64ビルドには、クライアントJVMも付属していませんでした。
古いバージョンの 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スペースの使用状況を他の多くの統計とともにリアルタイムで監視することもできます。
私が今気付いた違いの1つは、「クライアント」モードでは、JVMが実際に未使用のメモリをオペレーティングシステムに戻すように見えるのに対し、「サーバー」モードでは、JVMがメモリを取得すると、それを与えないことです。戻る。それはとにかくJava6を搭載したSolarisでどのように表示されるかです(prstat -Z
プロセスに割り当てられたメモリの量を確認するために使用します)。
Oracle のオンライン ドキュメントには、Java SE 7 に関するいくつかの情報が記載されています。
java - Windows の Java アプリケーション起動ページでは、オプション-client
は 64 ビット JDK では無視されます。
Java HotSpot クライアント VM を選択します。現在、64 ビット対応の jdk はこのオプションを無視し、代わりに Java HotSpot Server VM を使用します。
ただし、(物事を面白くするために)その下に次の-server
ように記載されています。
Java HotSpot サーバー VM を選択します。64 ビット対応の jdk では、Java HotSpot Server VM のみがサポートされるため、-server オプションは暗黙的です。これは、将来のリリースで変更される可能性があります。
Server-Class Machine Detectionページには、OS とアーキテクチャによって選択された VM に関する情報が表示されます。
これがどれだけJDK 6に当てはまるかはわかりません。
Goetz から - Java Concurrency in Practice:
- デバッグのヒント: サーバー アプリケーションの場合は、開発やテストの場合でも、JVM を呼び出すときに必ず
-server
JVM コマンド ライン スイッチを指定してください。サーバー JVM は、クライアント JVM よりも多くの最適化を実行します。たとえば、ループ内で変更されない変数をループから巻き上げます。開発環境 (クライアント JVM) で動作するように見えるコードが、デプロイメント環境 (サーバー JVM) では機能しなくなる可能性があります。たとえば、リスト 3.4 で変数 sleep を volatile として宣言するのを「忘れた」場合、サーバー JVM はテストをループから引き上げることができます (無限ループに変えます) が、クライアント JVM はそうしません。開発で現れる無限ループは、本番環境でしか現れない無限ループよりもはるかにコストがかかりません。
リスト 3.4. 羊を数える。
volatile boolean asleep; ... while (!asleep) countSomeSheep();
私の強調。YMMV
サーバー VM の IIRC は、起動時により多くのホットスポット最適化を行うため、実行速度は速くなりますが、起動に時間がかかり、より多くのメモリを使用します。クライアント VM は、起動を高速化するために、ほとんどの最適化を延期します。
編集して追加:これは Sun からの情報です。あまり具体的ではありませんが、いくつかのアイデアが得られます。
IIRC、それにはガベージコレクション戦略が含まれます。理論的には、クライアントとサーバーは存続期間の短いオブジェクトに関して異なるというものです。これは、最新の GC アルゴリズムにとって重要です。
サーバーモードのリンクです。残念ながら、彼らはクライアントモードについて言及していません。
これは、一般的なGCに関する非常に完全なリンクです。これはより基本的な記事です。サーバーとクライアントのどちらに対処するかはわかりませんが、これは関連資料です。
No Fluff Just Stuff では、Ken Sipe と Glenn Vandenburg がこの種のことについて素晴らしい話をしています。
2つの起動時間の違いには気づきませんでしたが、「-server」(Solarisサーバー、SunRaysを使用してアプリを実行するすべての人)を使用すると、アプリケーションのパフォーマンスが最小限に向上しました。それは1.5未満でした。
前回これを見たとき (確かに少し前のことですが)、私が気づいた最大の違いはガベージ コレクションでした。
ちゃんと覚えたら:
jvisualvmツールを使用して 2 つの Java VM、1 つのクライアント、1 つのサーバーを比較すると、ガベージ コレクションの頻度と効果、および世代数に違いがあることがわかります。
違いがよくわかるスクリーンショットが 2 枚ありましたが、サーバー VM のみを実装する 64 ビット JVM を使用しているため、再現できません。(そして、私のシステムでも 32 ビット バージョンをダウンロードして苦労することはできません。)
サーバー VM とクライアント VM の両方で Windows でいくつかのコードを実行しようとしたところ、両方で同じ世代モデルが得られたようです...