JVMの解決一般的な面接の質問

序文

JVMは、我々はあなたが正しい感じていないところがあり、助けたい、私自身の問題解決のためのアイデアを共有するために書き、古典的な顔のいくつかの質問をまとめたもので、その、その後の無償アップデートを歓迎します。

スタックメモリのオーバーフローは1.どのような条件が発生します。

アイデア:説明スタックが定義され、その後、なぜオーバーフローして、設定パラメータを説明するだろう記述され、[OK]を、我々はインタビュアーの手書きは、スタックオーバーフローのデモで与えることができます。

私の答え:

  • スタックは、民間のスレッドで、同じの彼のライフサイクルの糸で、それぞれの方法は、ローカル変数テーブルを格納するスタックフレームの実装で作成され、オペランドスタック、動的リンク、メソッドの終了は、情報を点灯します。そして、ローカル変数テーブルには、基本データ型、オブジェクト参照型が含まれています
  • スタックは、仮想マシンで許可された最大の深さをスレッドの深さよりも大きく要求された場合、にStackOverflowErrorは再帰呼び出しは、この結果を生成し、例外がスローされます。
  • 展開を完了するのに十分なメモリに適用され、または対応する仮想マシンのスタックを作成するための新しいスレッドを作成するのに十分なメモリがないときに、OutOfMemoryErrorが発生例外がスローされますJava仮想マシンではありません。(スレッドも開始しました)
  • JVMスタックサイズを調整する-Xssパラメータ

2.詳細なJVMのメモリ・モデル

アイデア: JVMのメモリ・モデルについてインタビュアーを描き、各モジュールの定義を例示し説明し、機能、および問題は、スタックオーバーフローとして、存在することができるため。

私の答え:

  • JVMのメモリ構造

プログラムカウンタ:スレッドへのプライベートバイトの命令アドレスを、実行する仮想マシンを記録するための行番号インジケータで実行される現在のスレッドのバイトコード。

Java仮想スタック:プライベートスレッド、基本データ型、オブジェクト参照、輸出や他の方法を格納します。

ネイティブメソッドスタック:と同様の仮想スタック、それはネイティブメソッドを提供しています、民間のスレッド。

Javaヒープ:メモリのJavaの最大の作品は、すべてのオブジェクトインスタンスは、ローカルJavaヒープ、GC回復の配列に格納され、スレッドが共有しています。

メソッド地区:ストアクラス情報がロードされている、定数、静的変数、コードデータと他のリアルタイムコンパイラ。(すなわち、永久的なバンド)、リサイクルおよび回収のターゲットは、主にアンロードの定数プールの種類、すべてのスレッドが共有します

3.JVMメモリは、新世代、古い時代の、永続的な世代に分割する理由。なぜエデンとサバイバーへの新世代。

アイデア:、どのようなJAVAスタックについてのトーク部門の新世代、そしてそれらの間の変換についての話、お互いの間で設定パラメータの一部(例:-XX:NewRatio、-XX:SurvivorRatio、など)、およびそれが分割される理由を説明最高の自分の理解に少しを追加します。

私の答え:

1)共有メモリ領域が分割されています

  • パイル+と=永続的な共有メモリ領域

  • + =永続的な地域別の方法では

  • Javaヒープ= +歳新生代

  • 新世代=エデン+ S0 + S1

構成パラメータの2)数

  • デフォルトでは、1の新世代(ヤング)比歳(旧)値:パラメータによって2は、-XX:NewRatio構成を。
  • デフォルト、エデム:から:へ= 8:1:1(パラメータ-XXによって:SurvivorRatio設定)
  • 生存オブジェクトが15倍の領域にコピーする(仮想マシンのパラメータに対応する-XX:+ MaxTenuringThreshold)

3)なぜなぜ我々は2つのサバイバー領域を設定する必要がありますか?エデンとサバイバーに分かれていますか?

  • 一度各マイナーGCのためのサバイバー、エデン地区は、存在しない場合、オブジェクトは、古い時代の生存に送信されます。歳とすぐに満たされるように、トリガメモリ空間主要GC。老齢のフルGCを行うために、新しい世代よりもはるかに大きいマイナーGCよりもはるかに長いを消費し、我々はエデンとサバイバーに分割する必要があります。
  • 遺族存在意義は、オブジェクトを減らすことですが、新しい世代の中で生き残ることができ、それは昔に送信されますサバイバーのみターゲットを16回マイナーGCを受けることを保証するために、事前に選別することにより、完全なGCの発生を低減、古い時代に送られました年。
  • 設定2つのサバイバー領域の最大の利点は、断片化を解決するだけでエデン、経験マイナーGCで新しいオブジェクトを作成することです、エデンでのライブオブジェクトは、エデンがクリアされて最初の遺族空間S0に移動されます。そしてそうエデンに地区は、再びいっぱいになるし、その後マイナーGC、エデンとS0(このプロセスは非常に重要である第二のブロックの生存空間S1にコピーされる対象の生存をトリガするためエデンにおけるS0及びS1から、複写アルゴリズム保証二部のライブオブジェクトは、断片化の発生を回避するために、連続したメモリ領域を占有)

オブジェクトは、古い年に昇格する方法フルGCプロセス4. JVMのように、

アイデア:最初のマイナーGC、メジャーGC、フルGCを説明し、Javaのヒープメモリ部門を記述し 、 それらの間の変換処理を説明します。

私の答え:

  • Javaヒープ= +歳新生代
  • 新世代=エデン+ S0 + S1
  • エデンエリアがスペースの一杯になると、Java仮想マシンがオブジェクトを生き残った、新世代のガベージコレクションに、マイナーGCをトリガするサバイバーエリアに転送されます。
  • ラージオブジェクト(Javaオブジェクトは、このような非常に長い文字列というように、連続したメモリ空間の多くを必要と)直接古い状態に
  • オブジェクトがエデンで生まれ、生きてまだ最初のマイナーGC後、およびサバイバーの言葉を収納された場合は、年齢が1に設定され、毎回マイナーGCは、年齢+1、生き残った一定の限度(15)よりも古い場合は、ました古い時代に状態を推進そのオブジェクトの古い時代の状態に長期生存
  • 旧のフルおよび複数のオブジェクトを収容することができないが - 、通常はマイナーGC後、フルGCが全体のヒープメモリをクリーンアップのフルGCになり、若い世代と旧世代を含みます
  • 主なGCはGC古い時代に発生したクリーン殿堂入り、多くの場合、少なくとも一つのマイナーGCを伴う、マイナーGCの10倍より遅いより

5.あなたは、ガベージコレクタの種類を、それぞれの長所と短所を知っている、との原則、プロセス、長所と短所を含め、下のCMS G1の一部をハイライトしてください。

アイデア:私たちは、典型的なガベージコレクタ、特にCMSとG1、その原則と違い、ガベージコレクションのアルゴリズムが関与していることを覚えておく必要があります。

私の答え:

1)いくつかのガベージコレクタ:

  • シリアルコレクター:シングルスレッドのコレクター、ごみの収集は、コピーアルゴリズムを使用して、世界を停止する必要があります。
  • ParNewのコレクター:マルチスレッド版のシリアルコレクタは、また、世界、複製アルゴリズムを停止する必要があります。
  • 並列スカベンジコレクター:コレクターの新世代、コレクタアルゴリズム、同時マルチスレッドコレクタをコピーするには、目的は、制御されたスループットを達成することです。仮想マシンが1分を費やすことを拒否100分の合計を実行している場合、スループットは99%です。
  • シリアル旧コレクター:シリアル・コレクターの古いバージョンの、シングルスレッドのコレクターは、アルゴリズムを整理するためにタグを使用します。
  • パラレル旧コレクター:並列スカベンジコレクターの古いバージョンの、マルチスレッド、マークの使用-ソートアルゴリズム。
  • CMS(並行マークスイープ)コレクター:最短目標復旧時間コレクタを得るためには、一時停止、マークスイープアルゴリズム、プロセスの操作:初期マーク、コンカレントマークと再マーク、同時がクリア、最後はスペースデブリの大規模なコレクションを生成します。
  • G1コレクター:タグのアルゴリズムを整理するために、最初のマーク、コンカレントマーク、最終マーク、選択マーカー:運用プロセスには以下のものが含まれますいいえスペースデブリない、正確に停止制御することができます。

2)CMSコレクタとコレクタG1差:

  • CMSコレクタは、古い時代のコレクターである、それは一緒に使用するシリアルおよびParNewコレクタの新しい世代で使用することができます。
  • G1コレクターのコレクションは、古いものと新しい世代の範囲、他のコレクターと組み合わせて使用​​する必要はありません。
  • コレクタ対象の最小滞留時間のCMSコレクタ;
  • G1コレクタ予測可能な停止時間のガベージコレクション
  • 、ガベージコレクションのアルゴリズムメモリの断片化が発生しやすい - CMSコレクタは「スイープマーク」を使用することです
  • 「マーク - 仕上げ」を使用してG1コレクタアルゴリズム、空間的な統合は、メモリスペースデブリを減少させます。

このよう並べ替え、メモリバリア、起こる-前に、メインメモリ、ワーキングメモリとして理解のどのくらいの知識6.JVMメモリモデル、。

アイデア:最初に、並べ替えているかを説明、揮発性の例で、Javaのメモリモデル図を描くメモリバリアは、インタビュアーが次のデモの説明を書いて与えるのがベストです。

私の答え:

1)Javaのメモリモデル図:

Javaのメモリモデルは、すべての指定変数は、メインメモリに格納され、各スレッドは、独自のワーキングメモリを持っているワーキングメモリは、スレッド内のスレッドを保持する変数に使用されるメインメモリのコピーのコピーである、スレッド変数すべての操作は、ワーキングメモリ内になければなりませんため、しかし直接読み込むと、メインメモリを書き込むことはできません異なるスレッド間でも直接他の変数のワーキングメモリにアクセスすることはできません、変数がスレッド間で渡されると同時に彼らのワーキングメモリとメインメモリ間でデータを必要としています。

2)コマンドの並べ替え。

ここでは、コードが見えます

public class PossibleReordering {
static int x = 0, y = 0;
static int a = 0, b = 0;

public static void main(String[] args) throws InterruptedException {
    Thread one = new Thread(new Runnable() {
        public void run() {
            a = 1;
            x = b;
        }
    });

    Thread other = new Thread(new Runnable() {
        public void run() {
            b = 1;
            y = a;
        }
    });
    one.start();other.start();
    one.join();other.join();
    System.out.println(“(” + x + “,” + y + “)”);
}
复制代码

動作結果が(1,0)、(0,1)又は(1,1)であってもよく、それは(0,0)であってもよいです。ので、実際の運用では、コード命令は、厳密にコードステートメントの実行順序に従ってではないかもしれません。最新のマイクロプロセッサは、順不同命令を実行するために使用される取得を回避すること、条件が許す場合、直後の命令を実行するための直流運転能力方法、(アウトオブオーダー実行、OoOE又はOOEをいいます。)次の命令3を待つために必要なデータによって引き起こされます。オーダー実行技術により、大幅プロセッサの効率を向上させることができます。そして、これはある命令の再配置

3)メモリバリア

メモリバリア、メモリフェンス命令として知られているが、特定の条件下でリオーダリング視認性の問題を制御するためのCPU、及びメモリです。

  • LoadLoadバリアは:ステートメントようLOAD1について、LoadLoad、後続のデータがアクセスされ読み出される読み出し動作前LOAD2、LOAD2と、読み出されLOAD1を読み取ることが保証データが完成します。
  • StoreStoreバリア:ステートメントようStore1ために、次の書き込み動作は、他のプロセッサに対して可視Store1書き込み動作を確保store2行われStore2、及び前; StoreStore。
  • LoadStoreバリア:ステートメントようLOAD1について、LoadStore; Store2、およびその後の書き込み動作がstore2ブラシれる前に、データが読み取られることを保証するためには、LOAD1が完了読み出されます。
  • StoreLoadバリア:ステートメントのためのそのようなStore1; StoreLoad; LOAD2前LOAD2、およびそれ以降のすべての読み取り操作はStore1がすべてのプロセッサに対して可視の書き込みを保証するために行います。これはコストが4つの最大の障壁です。ほとんどのプロセッサの実装では、この障壁は普遍的障壁、両方の他の3つのメモリバリア機能です。

4)起こり、前の原則

  • スレッド化が起こる-前に原則:同じスレッドでは、後者の操作帳EDITORIALが起こる-前の動作を。ハプン・ビフォア原則ロック:ロックが起こる-前に、同じロック、アンロック操作でロックを操作します。
  • 起こる-前に揮発性の原則:次のいずれかが起こる前に、この変数(もちろん、ライト動作を含む)にvolatile変数の操作を記述すること。
  • 原理はの転送前に起こる:Aが起こる前に、動作Bを操作した場合、BのC-起こる前の動作を操作する、操作C-起こる前に動作を制御します。
  • ハプン・ビフォア原則スレッドが開始:スレッド開始方法で発生-前に、他の方法でこのスレッドを。
  • 原則スレッドが起こる-前に割り込みを:割り込みスレッドのメソッド呼び出しが起こる-前に検出スレッドが送信されたコードを中断するために中断されます。
  • 起こる-前に原則のスレッドの終わり:すべての操作がスレッド起こる-前に終了検出スレッドです。
  • 起こる-前に作成された主な目的:オブジェクトを初期化する方法を確定するために彼の最初の呼び出しを完了しました。

あなたは両親を破るためにそれを委任することができ、簡単なクラスローダについて知っていることを教えてください7.、どのようにし破壊します。

アイデア:最初にあなたのクラスローダ委譲モデルの存在意義を伝えるために、クラスローダが何であるか、インタビュアーがマップを描くことができます説明は両親について言う、両親は最終的にデリゲートモデルを分割する方法を説明しました。

私の答え:

1)クラスローダとは何ですか?

クラスローダは、中クラスのオブジェクトに応じて、JVMのメモリにロードされたクラスファイルの完全修飾名を指定することです。

  • クラスローダ(ブートストラップクラスローダ)を起動します(HotSpotのために)C ++言語で実装、ライブラリーへのパスがメモリにロードされている指定libディレクトリまたは-Xbootclasspathパラメータ\ <JAVA_HOME>で店舗を担当しています。
  • 他のクラスローダ:Java言語で実装され、抽象ClassLoaderクラスから継承されました。以下のような:
  • 拡張クラスローダ(拡張クラスローダ):パスを指定し、<JAVA_HOME>すべてのライブラリーlib \ extディレクトリまたはシステム\変数のjava.ext.dirsをロードするための責任。
  • アプリケーションクラスローダ(アプリケーションクラスローダ)。指定されたライブラリにユーザクラスパス(クラスパス)をロードするための責任は、我々が直接このクラスローダを使用することができます。一般的に、我々は、カスタムクラスローダーのデフォルトを持っていない場合、ローダを使用することです。

2)親委譲モデル

親委任モデルのワークプロセスは、次のとおりです。

クラスローダークラスローダーが要求を受信した場合、それは最初にこのクラスをロードしようとするために所有していませんが、この要求は完了し、親クラスローダに委譲されます。彼らの検索で親ローダーは、指定されたクラス(すなわちClassNotFoundExceptionが)見つからない場合にのみ、各クラスローダが真である、サブローダは、独自のをロードしようとします。

親委任モデル図:

3)なぜ親はモデルを委任する必要がありますか?

ここでは、親が委任していない場合は、最初に考える、ユーザーがすることができませんjava.lang.Object上位の同じ名前を持つ独自のクラスを定義し同じ名前のjava.lang.Stringクラス、およびそれをクラスパスを入れ、その後、クラス間比較クラスと一意の結果は保証できませんので、なぜ親がモデルを委任するために必要?同じバイトコードの複数のコピーがメモリを防ぎます

4)どのように親委任モデルを破るには?

だけでなく、両親を破るためのメカニズムを委譲クラスローダを継承するクラスを、またして書き換えるとにfindClassにloadClass方法。

8.あなたはいくつかの主要なJVM引数を知っていることを教えてください

アイデア:これは、スタックのガベージコレクタに関する構成関連、ならびに関連の追加情報について言うことができます。

私の答え:

1)関連するスタック構成

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k 
-XX:MaxPermSize=16m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=0
复制代码

-Xmx3550m: 3550メートルへの最大ヒープサイズ。

-Xms3550m: 3550メートルの初期ヒープサイズを設定します。

-Xmn2g: 2グラムの若い世代のサイズを設定します。

-Xss128k:各スレッドのスタックサイズは128Kです。

-XX:MaxPermSizeを:永続的な世代のサイズは16メートルで設定

-XX:NewRatio = 4: 永久世代を除く)、旧世代の比率(エデンと2つのサバイバー領域を含む)若い世代を設定します。

-XX:SurvivorRatio = 4:エデンサバイバー若い世代領域の面積比の大きさを設定します。4に設定されている、サバイバーエデンゾーンを有する2つの領域の比は2:4、総面積サバイバー若い世代1/6

-XX:MaxTenuringThreshold = 0:ごみの最大の年齢を設定します。サバイバーエリアなし、直接古い世代にオブジェクトの0に設定すると、若い世代。

2)ガベージコレクタに関連します

-XX:+UseParallelGC
-XX:ParallelGCThreads=20
-XX:+UseConcMarkSweepGC 
-XX:CMSFullGCsBeforeCompaction=5
-XX:+UseCMSCompactAtFullCollection:
复制代码

-XX:+ UseParallelGC:パラレルガベージコレクタコレクタを選択します。

-XX:ParallelGCThreads = 20:パラレルコレクタに配置されたスレッドの数

-XX:+ UseConcMarkSweepGCを:設定し、古い同時コレクションを取りました。

-XX:CMSFullGCsBeforeCompaction:メモリ空間の同時収集整理、圧縮されませんので、それは作業効率が低下しながら、操作の期間後の「破片」を持つことになります。この値は、仕上げ、圧縮後に何回GCメモリ空間を実行するように設定されています。

-XX:+ UseCMSCompactAtFullCollection:旧世代のオープン圧縮。パフォーマンスが影響を受ける可能性がありますが、破片を除去することができます

3)補助情報関連

-XX:+PrintGC
-XX:+PrintGCDetails
复制代码

-XX:+ PrintGC出力フォーマット:

[GC 118250K-> 113543K(130112K)、0.0094143秒] [完全GC 121376K-> 10414K(130112K)、0.0650971秒]

-XX:+ PrintGCDetails出力フォーマット:

[GC [DefNew:8614K-> 781K(9088K)、0.0123035秒] 118250K-> 113543K(130112K)、0.0124633秒] [GC [DefNew:8614K-> 8614K(9088K)、0.0000665秒] [終身:112761K-> 10414K (121024K)、0.0433488秒] 121376K-> 10414K(130112K)、0.0436268秒

9.どのようにスレッドスタック情報を再生します。

アイデアは:質問に答えるための調査のラインと一緒に、これらの注文をjstack、JPS、頂上について語ったことができます。

私の答え:

  • プロセスIDを取得し、JPSを入力します。
  • トップ-hpは、このプロセスですべてのスレッドのCPU時間のかかるパフォーマンスを得るPID
  • jstack pidのコマンドは、スタックJavaプロセスの現在のステータスを表示するには
  • またはjstack -l>スタック情報/tmp/output.txtはtxtファイルを打ちます。
  • あなたはfastthreadスタックの位置、使用することができますfastthread.io/を

10.強い参照、ソフト参照、弱参照、仮想基準との間の差?

アイデア:私は参照の4つの定義についてお話しましょう、コードの話と組み合わせることができ、あなたはそれが使用弱参照でThreadLocalMap来る展開することができます。

私の答え:

1)強い参照

私たちは通常、新しいオブジェクトは強い参照、ObjectなどのOBJ =新しいオブジェクト()である。でも、メモリ不足の状況で、JVMはなく、このオブジェクトを回復しないのOutOfMemoryエラーをスローしていました。

2)ソフト参照

オブジェクトが唯一のソフト参照を持っている場合は、メモリ空間が十分にある、ガベージコレクタはそれを取り戻すしませんが、メモリ容量が不足している場合、これらのオブジェクトのメモリを再利用します。

SoftReference<String> softRef=new SoftReference<String>(str);     // 软引用
复制代码

用途:ソフト参照は、ブラウザの[戻る]ボタンなど、実際に重要な用途を有します。あなたが戻る押すとバックまたは再要求は、それがキャッシュから削除する場合、Webページの内容が表示されますか?これは、特定の実装方法に依存します。

(1)ウェブページのコンテンツをブラウジングの終了時にリサイクルする場合は、戻るを押し訪問前のページを表示するには、再構築する必要があります

(2)あなたは、メモリに保存しているページを閲覧した場合、メモリの無駄の多くを引き起こし、さらにはメモリのオーバーフローが発生します

次のコード:

Browser prev = new Browser();               // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用        
if(sr.get()!=null){ 
    rev = (Browser) sr.get();           // 还没有被回收器回收,直接获取
}else{
    prev = new Browser();               // 由于内存吃紧,所以对软引用的对象回收了
    sr = new SoftReference(prev);       // 重新构建
}
复制代码

3)弱参照

弱参照を持つオブジェクトは、より短いライフサイクルを持っています。オブジェクトは関係なく、現在のメモリ空間の、弱い参照を発見十分かどうかになると、ガベージコレクタスレッドのプロセスにそのメモリを再利用し、その管轄下のメモリ領域を走査します。

String str=new String("abc");    
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str=null;
等价于
str = null;
System.gc();
复制代码

4)仮想基準

オブジェクトのみファントム参照を保持し、それはすべての参照を持っていない場合、彼らはいつでもガベージコレクションである可能性が高いです。主にオブジェクトを追跡するために使用されるファントム参照は、ガベージコレクタ活性を回復しました。

更新する11

リファレンスと感謝

おすすめ

転載: juejin.im/post/5d35ca5b518825449c64bc31