インタビュー経験
数年前、アリがインタビューに行ってこの質問をしたことを覚えています。
Javaのオブジェクトはヒープに割り当てられていますか?理由を説明!
そのとき、私は驚いた表情で尋ねられ、すぐに完璧に砕かれました。そのとき、彼がテストしている知識ポイントがわかりませんでした。オブジェクトはヒープに割り当てられていませんか?結局、それ以上はありませんでした、私は戻って通知を待ちました。
オブジェクトの割り当て
ほとんどすべてのオブジェクトがヒープに割り当てられます。これは誰もがよく目にする文ですが、この文はすべてを意味するわけではありません。JVMのオブジェクトはスタックに割り当てることができますが、前提はエスケープ状態を判断することです。
オブジェクトのエスケープ状態
1. GlobalEscape
つまり、オブジェクトのスコープは現在のメソッドまたは現在のスレッドをエスケープします。いくつかのシナリオがあります。
- オブジェクトは静的変数です
- オブジェクトはエスケープされたオブジェクトです
- 現在のメソッドの戻り値としてのオブジェクト
2.パラメータエスケープ(ArgEscape)
つまり、オブジェクトはメソッドパラメータとして渡されるか、パラメータによって参照されますが、呼び出し中にグローバルエスケープは発生せず、この状態は呼び出されたメソッドのバイトコードによって決定されます。
3.逃げられない
つまり、メソッド内のオブジェクトはエスケープしません。
エスケープ分析コード
public class EscapeAnalysisTest {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
for (int i = 0; i < 50000000; i++) {
allocate(); } System.out.println((System.currentTimeMillis() - start) + " ms");
Thread.sleep(600000); }
static void allocate() {
MyObject myObject = new MyObject(2020, 2020.6); }
static class MyObject { int a; double b; MyObject(int a, double b)
{ this.a = a; this.b = b;
} }}
このコードを呼び出すプロセスで、オブジェクトmybojectはグローバルエスケープに属し、JVMはそれをスタックに割り当てることができます
次に、DoEscapeAnalysisスイッチをオン/オフして違いを観察します。
エスケープ分析を有効にする(JVMはデフォルトで有効になっています)
実行速度を表示
エスケープ分析をオフにする
実行速度を表示
テスト結果は、エスケープ分析を有効にすると、コードの実行パフォーマンスに大きな影響があることを示しています。では、なぜそのような影響があるのでしょうか。
エスケープ分析
エスケープで解析されたオブジェクトをスタックに配置できる場合は、オブジェクトのライフサイクルはスレッドに従い、ガベージコレクションは不要ですが、このメソッドを頻繁に呼び出すと、パフォーマンスが大幅に向上します。
エスケープ分析を採用した後、エスケープを満たすオブジェクトがスタックに割り当てられます
エスケープ分析が有効になっておらず、オブジェクトがヒープに割り当てられているため、ガベージコレクションが頻繁にトリガーされ(ガベージコレクションはシステムパフォーマンスに影響を与えます)、コードの実行が遅くなります
コード検証
GC印刷ログを有効にする
-XX:+ PrintGC
エスケープ分析をオンにする
GCログがないことがわかります
エスケープ分析をオフにする
エスケープ分析がオフになっていて、JVMがガベージコレクション(GC)を頻繁に実行していることがわかります。この操作がパフォーマンスに大きな違いを引き起こしています。
総括する
JVMは、多くの面接担当者が聞きたいものです。ただし、JVMには幅広く深い知識システムがあるため、面接担当者の質問の中には非常にトリッキーなものもあります。そのため、よくわからない場合は、軽く答えるべきではありません。いくつかの知識は、経験するための練習が必要です。これらの知識のポイントを落ち着いて説明すると、面接で主導権を握ることができます。