[[322350]] このような問題に遭遇したことはありませんか? - オンラインシステムが突然フリーズし、システムにアクセスできなくなったり、OOM が発生したりします。
- オンライン JVM GC 問題を解決したいのですが、どこから始めればよいかわかりません
- 新しいプロジェクトが立ち上げられたとき、さまざまな JVM パラメータ設定について混乱しました。私はデフォルトのものを使い、その後JJ
- 面接を受けるたびに、JVM の原則と概念のいくつかを読み直さなければなりません。
このスローガンはよく書かれています。在宅勤務中に JVM について学ぶ機会を活用します。全体的な知識ポイントは次のとおりです。 Java 開発者は皆、JVM が Java 仮想マシンであることを知っています。学校で使っていた VM は仮想マシンとも呼ばれます。まずは比較してみましょう。 仮想マシンとJava仮想マシン いわゆる仮想マシンは仮想コンピュータです。一連の仮想コンピュータ命令を実行するために使用されるソフトウェアです。一般的に、仮想マシンはシステム仮想マシンとプログラム仮想マシンに分けられます。 - VirtualBox と VMware はシステム仮想マシンです。これらは物理コンピューターの完全なシミュレーションであり、完全なオペレーティング システムを実行できるソフトウェア プラットフォームを提供します。
- プログラム仮想マシンの代表的なものは、単一のコンピュータ プログラムを実行するために特別に設計された Java 仮想マシンです。 Java 仮想マシンで実行される命令は、Java バイトコード命令と呼ばれます。
JVMとは JVM は Java Virtual Machine の略です。 JVM はコンピューティング デバイスの仕様です。実際のコンピュータ上でさまざまなコンピュータ機能をシミュレートして実装された架空のコンピュータです。 Java 仮想マシンはバイナリ バイトコードの実行環境であり、バイトコードを読み込み、対応するプラットフォームで実行するためのマシン命令に解釈/コンパイルする役割を担います。各 Java 命令には、オペランドの取得方法、オペランドの処理方法、処理結果の保存場所など、Java 仮想マシン仕様で詳細な定義があります。 特徴 - 一度コンパイルすればどこでも実行可能(クロスプラットフォーム)
- 自動メモリ管理
- 自動ガベージコレクション機能
バイトコード 通常、Java バイトコードと呼ばれるものは、Java 言語で記述されたバイトコードを指します。正確に言うと、JVM プラットフォーム上で実行できるバイトコードの形式はすべて同じなので、総称して JVM バイトコードと呼びます。 異なるコンパイラで同じバイトコード ファイルをコンパイルでき、バイトコード ファイルは異なる JVM 上で実行することもできます。 Java 仮想マシンは必ずしも Java 言語に関連しているわけではありません。これは、特定のバイナリ ファイル形式 (クラス ファイル形式) にのみ関連付けられます。クラス ファイルには、Java 仮想マシン命令セット (バイトコードとも呼ばれます) とシンボル セット、およびその他の補助情報が含まれています。 Javaコード実行プロセス JVMの場所 JVM はオペレーティング システム上で実行され、ハードウェアと直接やり取りすることはありません。 JDK (Java Development Kit) は、Java 言語用のソフトウェア開発キット (SDK) です。 JDK は、物理的には Java 言語、ツール、JRE、および JVM のコレクションとして存在します。 JVM 全体構造 JVM アーキテクチャ モデル Java コンパイラによって入力される命令ストリームは基本的にスタックベースの命令セットアーキテクチャであり、もう 1 つの命令セットアーキテクチャはレジスタベースの命令セットアーキテクチャです。 2 つのアーキテクチャの違い: - スタックベースのアーキテクチャにより、設計と実装が容易になり、リソースが制限されたシステムに適しています。レジスタ割り当ての難しさを回避し、割り当てにゼロアドレス命令を使用します。命令ストリーム内の命令のほとんどはゼロアドレス命令であり、その実行プロセスは操作スタックに依存します。命令セットが小さくなり、コンパイラの実装が容易になります。ハードウェアのサポートは不要であるため、移植性が向上し、クロスプラットフォームの実装が容易になります。
- レジスタベースアーキテクチャの特性の典型的な応用例は、従来の PC や Android の Davlik 仮想マシンなどの X86 バイナリ命令セットです。命令セットアーキテクチャはハードウェアに完全に依存しており、移植性が低い。優れたパフォーマンスとより効率的な実行。操作を完了するために必要な命令が少なくなります。ほとんどの場合、レジスタ アーキテクチャに基づく命令セットは、1 アドレス命令、2 アドレス命令、および 3 アドレス命令に基づくことが多いのに対し、スタック アーキテクチャに基づく命令セットは、0 アドレス命令に基づいています。
クロスプラットフォーム設計のため、Java 命令はすべてスタックに基づいて設計されています。プラットフォームによって CPU アーキテクチャが異なるため、レジスタベースで設計することはできません。利点は、クロスプラットフォーム、小さな命令セット、および簡単なコンパイラ実装です。欠点は、パフォーマンスが低下し、同じ機能を実現するためにより多くの命令が必要になることです。 スタックアーキテクチャに基づいてJVMコード実行プロセスを分析する クラス ファイルがあるディレクトリに入り、javap -v xx.class を実行して逆解析を行う (または IDEA プラグイン Jclasslib を介して直接表示する) と、現在のクラスに対応するコード領域 (アセンブリ命令)、ローカル変数テーブル、例外テーブル、コード行オフセット マッピング テーブル、定数プールなどの情報が表示されます。 上図の 1+2 を例に挙げます。 - クラスファイル /Users/starfish/workspace/myCode/starfish-learning/starfish-learn/target/classes/priv/starfish/jvm/JVM1.class
- 最終更新日 2020-2-7;サイズ487 バイト
- MD5 チェックサム 1a9653128b55585b2745270d13b17aaf
- 編集元 「JVM1.java」
- パブリッククラス priv.starfish.jvm.JVM1
- ソースファイル: "JVM1.java"
- マイナーバージョン: 0
- メジャーバージョン: 52
- フラグ: ACC_PUBLIC、ACC_SUPER
- 定数プール:
- #1 = メソッド参照 #3.#22 // java/lang/Object. 「<init>」 :()V
- #2 = クラス #23 // priv/starfish/jvm/JVM1
- #3 = クラス #24 // java/lang/Object
- #4 = Utf8 <init>
- #5 = Utf8()V
- #6 = Utf8 コード
- #7 = Utf8 行番号テーブル
- #8 = Utf8 ローカル変数テーブル
- #9 = Utf8 これ
- #10 = Utf8 Lpriv/starfish/jvm/JVM1;
- #11 = Utf8 メイン
- #12 = Utf8 ([Ljava/lang/String;)V
- #13 = Utf8 引数
- #14 = Utf8 [Ljava/lang/String;
- #15 = Utf8 i
- #16 = Utf8 I
- #17 = Utf8 j
- #18 = Utf8k
- #19 = Utf8 メソッドパラメータ
- #20 = Utf8 ソースファイル
- #21 = Utf8 JVM1.java
- #22 = NameAndType #4:#5 // "<init>" :()V
- #23 = Utf8 priv/ヒトデ/jvm/JVM1
- #24 = Utf8 java/lang/オブジェクト
- {
- パブリックpriv.starfish.jvm.JVM1();
- フラグ: ACC_PUBLIC
- コード:
- スタック=1、ローカル=1、args_size=1
- 0: ロード_0
- 1:invokespecial #1 // メソッド java/lang/Object。 「<init>」 :()V
- 4:戻る
- 行番号テーブル:
- 3行目: 0
- ローカル変数テーブル:
- 開始長さスロット名署名
- 0 5 0 この Lpriv/starfish/jvm/JVM1;
-
- 公共 静的void main(java.lang.String[]);
- フラグ: ACC_PUBLIC、ACC_STATIC
- コード:
- スタック=2、ローカル=4、args_size=1
- 0: iconst_1 //コロンの前の数字はプログラムカウンタの番号を示し、定数1がスタックにプッシュされます
- 1: istore_1 //オペランドスタック1に保存します。1はオペランドスタックのインデックス位置を表します。
- 2: アイコンst_2
- 3: istore_2
- 4: iload_1 //ロード
- 5: ロード2
- 6: iadd // 定数をポップして合計する
- 7: istore_3 //インデックス3のオペランドスタックに格納
- 8:戻る
- 行番号テーブル:
- 6行目: 0
- 7行目: 2
- 8行目: 4
- 9行目: 8
- ローカル変数テーブル:
- 開始長さスロット名署名
- 0 9 0 引数 [Ljava/lang/String;
- 2 7 1 私
- 4 5 2 j 私
- 8 1 3 キロ 私
- メソッドパラメータ: 長さ = 0x5
- 01 00 0D 00 00
- }
JVM ライフサイクル 仮想マシンの起動 Java 仮想マシンの起動は、仮想マシンの特定の実装によって指定されるブートストラップ クラス ローダーを通じて初期クラスを作成することによって完了します。 仮想マシンの実行 - 実行中のJava仮想マシンには、Javaプログラムを実行するという明確なタスクがあります。
- プログラムの開始時に実行され、プログラムの終了時に停止します。
- いわゆる Java プログラムを実行する場合、実際に実行されるのは Java 仮想マシンと呼ばれるプロセスです。
- 同じマシン上で 3 つのプログラムを実行すると、3 つの Java 仮想マシンが実行されることになります。 Java 仮想マシンは常に main() メソッドから開始します。このメソッドは public で、void を返し、文字列配列のみを受け入れる必要があります。プログラムを実行するときは、main() メソッドを含むクラスの名前を Java 仮想マシンに指定する必要があります。
仮想マシンを終了する いくつかの状況があります: - プログラムは正常に終了します。
- プログラムの実行中に例外またはエラーが発生し、異常終了しました
- Java仮想マシンのプロセスは、オペレーティング システム エラーのため終了しました。
- スレッドがRuntimeクラスまたはSystemクラスのexitメソッド、またはRuntimeクラスのhaltメソッドを呼び出し、Javaセキュリティマネージャもこのexitまたはhalt操作を許可します。
- さらに、JNI (Java Native Interface) 仕様では、JNI 呼び出し API を使用して Java 仮想マシンをロードまたはアンロードする場合の Java 仮想マシンの終了について説明しています。
Java および JVM の仕様 Java言語と仮想マシンの仕様 JVM 開発の歴史 JDK バージョンのアップグレードは、言語や機能の特徴に反映されるだけでなく、コンパイルおよび実行する Java 仮想マシンのアップグレードも含まれます。 - 1990 年、サン コンピュータ コーポレーションでは、パトリック ノートン、マイク シェリダン、ジェームズ ゴスリングが率いるグリーン チームが、Oak という新しいプログラミング言語を開発しました。この言語は後に Java と命名されました。
- 1995 年に、Sun は Java および HotJava 製品を正式にリリースし、Java が初めて一般公開されました。
- 1996 年に JDK 1.0 がリリースされたとき、純粋に解釈された Java 仮想マシンの実装である Sun Classic VM が提供されました。
- 1997 年に JDK 1.1 がリリースされたとき、仮想マシンは変更されず、引き続き Sun Classic VM がデフォルトの仮想マシンとして使用されていました。
- 1998 年に JDK 1.2 がリリースされたとき、Solaris プラットフォーム上で実行される Exact VM 仮想マシンが提供されましたが、この時点では Sun Classic VM がまだデフォルトの Java 仮想マシンとして使用されていました。同時に、JSP/Servlet および EJB 仕様がリリースされ、Java は J2EE、J2SE、J2ME に分割されました。
- 2000 年に JDK1.3 がリリースされ、デフォルトの Java 仮想マシンが Sun Classic VM から Sun HotSopt VM に変更され、Sun Classic VM がバックアップ仮想マシンとして使用されるようになりました。
- 2002 年に JDK 1.4 がリリースされ、Sun Classic VM は商用仮想マシンの段階から撤退しました。これまで、Sun HotSpot VM がデフォルトの仮想マシンとして使用されていました。
- 2003年にJavaプラットフォーム用のScalaが正式にリリースされ、同年にGroovyもJava陣営に加わった。
- 2004年にJDK1.5がリリースされ、JDK5.0に改名されました。
- 2006年にJDK6がリリースされました。同年、Java がオープンソース化され、OpenJDK が設立されました。当然のことながら、Hotspot仮想マシンはOpenJDKのデフォルトの仮想マシンにもなりました。
- 2008年にオラクルはBEAを買収し、JRockit仮想マシンを手に入れた。
- 2010年にオラクルはサンを買収し、Java商標とHotSpot仮想マシンを獲得した。
- 2011年にJDK7がリリースされました。 JDK1.7u4 では、新しいガベージ コレクター G1 が正式に有効化されました。
- 2014年にJDK8がリリースされ、PermGenがMetaSpaceに置き換えられました。
- 2017年にJDK9がリリースされ、CMSに代わってG1がデフォルトのGCとして設定されました。
サンクラシックVM - 世界初の商用 Java 仮想マシン。これは 1996 年に Java 1.0 のリリースとともにリリースされ、JDK 1.4 で完全に廃止されました。
- この仮想マシンはインタープリターのみを提供します。
- JIT コンパイラを使用する場合は、プラグインを使用する必要があります。ただし、JIT コンパイラを使用すると、JIT が仮想マシンの実行システムを引き継ぎ、インタープリターは動作しなくなります。インタプリタとコンパイラは連携して動作できません。
- ホットスポットにはこの仮想マシンが組み込まれています
正確なVM - その実行システムには、ホットスポット検出、2 レベルのジャストインタイム コンパイラ、コンパイラとパーサーの混合動作モードなど、最新の高性能仮想マシンの基本がすでに備わっています。
- 正確なメモリ管理を使用します。仮想マシンはメモリ内の特定の場所にある特定のタイプのデータを認識できます。
- これは商用アプリケーションでは短期間のみ存在し、より高度な HotSpot VM に置き換えられました。
サンホットスポットVM - これは Sun JDK および OpenJDK に含まれる仮想マシンであり、現在最も広く使用されている Java 仮想マシンです。
- これは、Sun の以前の 2 つの商用仮想マシンの利点 (正確なメモリ管理など) を継承し、ホット コード検出テクノロジ (実行カウンタを通じて最もコンパイルに値するコードを見つけ、メソッド単位でコンパイルするように JIT コンパイラに通知する) などの独自の新しい技術的利点も多数使用します。
- Oracle はそれぞれ BEA と Sun を買収し、JROKit のガベージ コレクターと MissionControl サービス、HotSpot の JIT コンパイラとハイブリッド ランタイム システムを使用するなど、JROKit VM と HotSpot VM を JDK8 に統合しました。
BEA JRockit VM - サーバー側アプリケーションに重点を置いており、内部にパーサーの実装は含まれていません。
- 世界最速のJVMであると主張している
IBM J9 VM - 正式名称: IBM Technology for Java Virtual Machine、IT4J とも呼ばれ、内部コード: J9
- 市場での位置付けは、HotSpot、サーバー、デスクトップ アプリケーション、組み込みなどの多目的 VM に近いです。
- 現在最も影響力のある3つの商用仮想マシンの1つ
Azul VM、Liquid VM、Apache Harmony、TaobaoJVM、Graal VM など、多数の仮想マシンがあります。 |