目次
JVMメモリ構造
JVMメモリ空間は、メソッド領域、ヒープ、Java仮想マシンスタック、ローカルメソッドスタック、およびプログラムカウンタの5つの部分に分かれています。
共有スレッド:メソッド領域、ヒープ
スレッドプライベート:仮想マシンスタック、ローカルメソッドスタック、プログラムカウンター
メソッド領域:定数、静的変数、クラス情報、実行時定数プール(リテラル、シンボリック参照)。
ヒープは主に配列、クラスインスタンスオブジェクト、文字列定数プールなどを格納します。
スタックには、基本型変数、ローカル変数、オブジェクト参照(アドレス)などの変数が格納されます。
ローカルメソッドを実行します(Java実装ではなく、c実装メソッド)
プログラムカウンタ:スレッドが切り替わると、実行位置が記録され、後で再実行されます。
スタックとヒープの関係は、スタックの内容がスタックされ、スタックの参照アドレスがスタックされることです。
スタック
クラス内のメソッドには、スタック内にスタックフレームがあります。スタックフレームには、ローカル変数テーブル、オペランドスタック、メソッド出口、および動的リンクが含まれます。仮想マシンは、メソッドの実行後にスペースを解放します。
ローカル変数テーブル:変数を格納します
オペランドスタック:計算中に、オペランドスタックにプッシュされ、最終的にスタックの最上位から取り出されます。
メソッド終了:メソッド終了時のリターンアドレスを指定します。
ダイナミックリンク:シンボル参照の一部はクラスのロード段階で直接参照に変換され、他の部分は実行時に直接参照に変換されます。この部分はダイナミックリンクと呼ばれます。(静的分析|動的リンク)
スタックオーバーフロー:メソッドの再帰により、スタックオーバーフローが発生しやすくなります。再帰的であるため、メソッドは終了していません。そのため、変数は常に作成され、スタックスペースがいっぱいになり、オーバーフローが発生します。
スタックオーバーフローコード:
public class Test {
public void test(){
String a;
test();
}
public static void main(String[] args) {
Test t =new Test();
t.test();
}
}
ヒープ
ヒープにはオブジェクトと配列が格納され、新しいものはすべてヒープに配置されます。
スタックとヒープの関係は、スタックの内容がスタックされ、スタックの参照アドレスがスタックされることです。
しきい値を超えるヒープは、一般的なメモリオーバーフローOutOfMemoryErrorです。
ヒープは動的に割り当てられたメモリであり、不連続なメモリ領域であり、Javaガベージコレクタによって管理されます。
public class Test {
public static void main(String[] args) {
List list = new ArrayList<>();
while (true) {
list.add(1);
}
}
}
スタックとヒープの関係:スタックオブジェクトの内容、スタックオブジェクトの参照アドレス。
ガベージコレクション
物体の死を判断する方法
オブジェクトの死を判断する方法:参照カウント法と到達可能性分析法。
参照カウント方法は、カウンタ値によって制御されます。参照されると、1ずつ増加し、参照は1ずつ減少します。短所:AはBを参照し、BはAを参照し、リサイクルできません。循環参照。
到達可能性分析の方法は、GCROOTとして安定したオブジェクトを選択し、到達可能なオブジェクトを見つけて、到達できない場合はそれを再利用することです。短所:メモリの断片化が発生します。
ガベージコレクションアルゴリズム
ガベージコレクションアルゴリズムには、参照カウント方法、マーククリアアルゴリズム、コピーアルゴリズム、マーク圧縮(編成)アルゴリズム、インクリメンタルアルゴリズムが含まれます。
参照カウント方法:オブジェクトが他のオブジェクトによって参照されている場合、そのカウンターは1ずつ増加し、参照は1ずつ減少し、オブジェクトのカウンター値はリサイクル時に0になります。短所:循環参照はリサイクルできない場合があります。
マーク除去アルゴリズム:ルートノードに従って到達可能なオブジェクトを検索し、到達できない場合はそれらを再利用します。短所:スペースデブリが発生します。
コピーアルゴリズム(新世代のシリアルガベージコレクターで使用):1分あたり2ブロックのスペースが再利用時に別の領域にコピーされ、この領域が削除されます。
マーク圧縮アルゴリズム(旧時代に使用):マークスイープアルゴリズムに基づいていくつかの最適化を行いました。メモリスペースで、到達可能なオブジェクトにマークを付け、それらをメモリの片側に圧縮してから、他のオブジェクトを削除して、メモリの断片化が発生しないようにします。
ガベージコレクター
並列スカベンジ レプリケーションアルゴリズム、重要な機能は次のとおりです。システムのスループットに注意を払います。
並列OLD はマーク圧縮アルゴリズムを使用します
CMSコレクターの マークスイープアルゴリズムリカバリの一時停止時間は比較的短くなりますが、それに応じてスループットが犠牲になります。B/ Sアーキテクチャに適しています。
G1 コレクタ(ごみファースト) G1コレクタは、現在、最新のガベージコレクタであるCMSコレクターと比較すると、G1コレクタが基づいている。マーク-圧縮アルゴリズム、それはメモリの断片化を生成しません。
Javaヒープ全体を、同じサイズの複数の独立したリージョン(リージョン)に分割します。リージョンセットは、若い世代と古い世代として定義されますが、物理的な障壁ではなくなりました。
jdk1.7デフォルトのガベージコレクタParallelScavenge(新世代)+ Parallel Old(旧世代)
jdk1.8デフォルトのガベージコレクタParallelScavenge(新世代)+ Parallel Old(旧世代)
jdk1.9デフォルトのガベージコレクターG1
同期されたキーワード
同期原理
解体てjavapを使用すると、基礎となるJVMの手順を参照することができます。1つのがありmonitorenterと2 monitorexitロックと解除がロックされている命令は、。1つの監視出口は正常で、もう1つは異常です。
ロックのアップグレードのプロセスもあります。
ロックアップグレード
オブジェクトは、オブジェクトヘッダー、インスタンス変数、パディングバイトの3つの部分に大別できます。
オブジェクトヘッダーは、MarkWordとKlass Point(型ポインター)で構成されます。KlassPointは、オブジェクトのクラスメタデータへのポインターです。MarkWordは、オブジェクト自体のランタイムデータを格納するために使用されます。
インスタンス変数は、親クラスの属性情報を含むオブジェクトの属性情報を、4バイトに従って整列して格納します。
充填文字。仮想マシンではオブジェクトバイトが8バイトの整数倍である必要があるため、この整数倍を構成するために充填文字が使用されます。
たわみロック-「軽量ロック-」重量ロック
具体的:競合が発生するたびに(単一スレッド)-「バイアスロックの導入-複数のスレッドが競合する-」軽量ロックの導入-競合するスレッドは、他に競合が開始される場合、スピンして待機します- -"ヘビーウェイトロックの導入---スレッドはブロックされますが、CPUはスピン操作を消費しなくなります。
バイアスロック
jdk1.6より前は、Synchronizedは依然として重いロックであり、パフォーマンスはあまり良くありませんでした。Hotspotは、毎回競合するスレッドがそれほど多くないことを発見したため、偏ったロックがありました。
スレッドIDは、オブジェクトヘッダーとスタックフレームのマークワードに配置されます。同じスレッドが再び入ると、同じIDであることがわかり、直接入ります。
同じスレッドが同期ブロックに入らない場合、Kclasが指すコンテンツに従って、同じスレッドが生きているかどうかを確認します。
(1)停止すると、CASは新しいスレッドIDを再ロックして更新します。
(2)存続する場合は、スタックフレームに移動して、ロックオブジェクトを保持する必要があるかどうかを確認します。
(2.1)保持する必要がなくなった場合は、それを取り消して、新しいスレッドIDに再度バイアスをかけます。
(2.2)それでもロックを保持する必要がある場合は、スレッドを一時停止し、バイアスされたロックをキャンセルして、ロックを軽量ロックにアップグレードします。
バイアスされたロックは、パラメーター構成によってキャンセルできます-XX:-UseBiasedLocking = false
軽量ロック
競合するスレッドが少なく、待機時間が長くない場合は、軽量ロックを使用して、スピンによってロックが解放されるのを待ちます。
複数の軽量ロックがあります。
(1)スレッドの場合、2番目のスレッドが入って、ロックオブジェクトのオブジェクトヘッダーがすでに占有されていることを検出すると、スピンして待機します。待機時間が長い場合は、ヘビーウェイトロックにアップグレードされます。 。
(2)3番目のスレッドが入って来て、別のスレッドが回転して待機していることを検出し、それもヘビーウェイトロックにアップグレードされます。
注:ロックをアップグレードした後は、ダウングレードすることはできません。
インタビューの回答:同期ロックアップグレードのアイデア1:
1.これはjdk1.6以降の最適化です。Hotspotの作成者は、競合するスレッドがそれほど多くない場合は常に、バイアスロックにつながることを発見しました。バイアスロックはオブジェクトヘッダーの概念です。マークワードとマークワードがあります。オブジェクトヘッダーに。kclassポイント、markwordはスレッドIDおよびその他のランタイム情報を格納します。スレッドが入ると、casはスレッドIDを更新しますが、ロックは解放されず、同じスレッドが次回直接入ることができます。
2.競合する複数のスレッドがある場合、この時点でcasが失敗すると、最初にオブジェクトヘッダーに移動して、それが生きているかどうかを確認し、次にスタックフレームに移動して、存続可能かどうかを確認します。にアップグレードされます。軽量ロック。3.軽量ロックとは、糸が回転することを意味します。回転数が増えると、重量ロックにアップグレードされます。もう1つは、より多くのスレッドが入って誰かが回転している場合、それらもヘビーウェイトロックにアップグレードされるということです。
理解力:
部分ロック:トイレに行くために並んでいる必要はありません、あなたは一人で家にいます、あなたはドアをロックする必要はありません、そしてあなたは毎回直接入って来ます。(シングルスレッド)
軽量ロック:友人が家にやって来て、友人がトイレに行きたがっています。しばらく外で待つだけで、ドアをロックする必要はありません。(スレッド数が少なく、競争が少なく、時間が短く、ブロッキングがありません)
ヘビーウェイトロック:たくさんの友達が家にやって来て、全員がトイレに駆けつけたので、ドアをロックしました。(多数のスレッドが競合してブロックします)