インタビューでこの質問を聞いたのですが、答えられませんでした。その後、インターネットで検索しましたが、まだ答えが見つかりませんでした。ガベージを収集するときに JVM が停止中の一時停止中にスレッドを停止する方法と、それらを再実行する方法を教えてください。
1 に答える
少なくとも HotSpot と OpenJDK の場合、JVM はセーフ ポイントを使用して各スレッドでアプリケーションのフローを停止します。これは、JITed コードで導入されるか、解釈されたコードのバイトコード マッピングを変更することによって行われます (詳細については、Alexey Ragozin によるこの投稿を参照してください)。
ストップ・ザ・ワールドの一時停止を処理するときにセーフポイントが追加の問題になる可能性がある理由については、Gil Tene によるこの回答も参照してください。
Hotspot/OpenJDK のセーフポイント メカニズムの詳細を以下に示します (私が理解しているように、私は専門家ではありません) (たとえば、safepoint.cppの 154 行を参照)。上記のリソースに基づいています。 Cliff の記事Azul Systemsブログ (サイトから消えたようです) をクリックします。
セーフポイントに到達
JVM はアプリケーションからフローの制御を取得する必要があるため、スレッドの現在の状態に依存します。
ブロックされた
JVM はすでにそのスレッドを制御しています。
解釈されたコードの実行
インタプリタは、各バイトコード評価の前にセーフポイント チェックが行われるモードに (ディスパッチ テーブルを交換することによって) 入ります。
ネイティブ コードの実行(JNI)
JNIコードはセーフポイントで実行され、Javaにコールバックするか、特定のJVMメソッドを呼び出す場合を除き、実行を継続できます。その時点で、セーフポイントを離れるのを防ぐために停止する場合があります(コメントについてはNitsanに感謝します)。
コンパイル済みコードの実行
JVM は特定のメモリ ページ (セーフポイント ポーリング ページ) を読み取り不能にします。これにより、そのページの定期的な読み取り (JIT コンパイラによってコンパイルされたコードに挿入される) が失敗し、JVM ハンドラーに送られます。
VM で実行中または遷移中の状態 (VM 内でも)
とにかく、フローはある時点でセーフポイント チェックを通過するため、VM はそれを待ちます。
セーフポイントで停止
スレッドがセーフポイントに到達し、JVM によって制御されると、JVM は単純にスレッドの終了をブロックします。すべてのスレッドが停止した場合 (つまり、世界が停止した場合)、JVM はガベージ コレクションを実行し、すべてのスレッドを解放して実行を再開できます。
詳細については、当面の間、Nitsan Wakart によって書かれたセーフポイントに関するこのブログ投稿を参照してください (それ自体にはさらに多くの参照があります)。