[パフォーマンスの最適化]インタビュアー:Javaのオブジェクトは必ずしもヒープに割り当てられますか?

前に書く

Javaの学習を始めてから、Javaのオブジェクトはヒープ上に作成され、オブジェクトへの参照がスタックに配置されるというビューに触れましたが、このビューは本当に正しいのでしょうか?それが正しければ、インタビュアーは「Javaのオブジェクトは必然的にヒープに割り当てられますか?」と尋ねるのはなぜですか?この質問はどうですか?私たちがJavaから植え付けられたこの見方には疑問の余地があるようです。

面接について

タイトルのインタビューの質問は次のとおりです。Javaのオブジェクトは必ずしもヒープに割り当てられますか?

インタビュアーが尋ねると、一部の友人は頭の中で考えます。私はJavaの学習の最初から知っていました。Javaのオブジェクトはヒープに作成され、オブジェクトへの参照はスタックに格納されるため、Javaのオブジェクトヒープに割り当てられています!そうではありませんか?

ここに画像の説明を挿入

このように答えると、直接合格します。

多分まだ理解していない友達もいるでしょう。

インタビュー質問回答

まず、この質問への回答を先に述べますが、ここでは、このインタビューの質問に簡単に回答し、後で関連する分析を行います。

これに答えることができます。JVMはエスケープ分析を通じて新しいオブジェクトの使用範囲を分析し、このオブジェクトをヒープに割り当てるかどうかを決定できるため、Javaのオブジェクトは必ずしもヒープに割り当てられるわけではありません。

ここでは、エスケープ分析という新しい用語に触れています。多くの友達はよくわからないと思いますので、これからも見下していきましょう。

ここに画像の説明を挿入

エスケープ分析

エスケープ分析の概念

まず、脱出分析について公式形式で話しましょう。エスケープ分析は、プログラムのポインターがアクセスできる場所を分析できる、ポインターのダイナミックレンジを決定する静的分析です。

JVMジャストインタイムコンパイルのコンテキストでは、エスケープ分析により、新しく作成されたオブジェクトがエスケープするかどうかが決定されます。ジャストインタイムコンパイルは、オブジェクトがエスケープするかどうかを判断します。1つはオブジェクトがヒープ(静的フィールドまたはヒープ内のオブジェクトのインスタンスフィールド)に格納されているか、もう1つはオブジェクトが不明なコードに渡されたかどうかです。

これらの概念と直接言えば、実際には少しめまいがするので、2つの例を見てみましょう。

ここに画像の説明を挿入

オブジェクトエスケープの例

典型的なオブジェクトエスケープは、次のとおりです。オブジェクトはメンバー変数または静的変数にコピーされ、この時点で変数がエスケープされ、外部で使用できます。

次のコードを使用して、この現象を表すことができます。

/**
 * @author binghe
 * @description 对象逃逸示例1
 */
public class ObjectEscape{
    
    
    private User user;
    public void init(){
    
    
        user = new User();
    }
}

ObjectEscapeクラスにはメンバー変数userがあり、init()メソッドでは、Userクラスのオブジェクトを作成して、メンバー変数userに割り当てます。このとき、オブジェクトはメンバー変数にコピーされ、外部で使用される可能性があり、このとき変数はエスケープされます。

別の典型的なシナリオは次のとおりです。オブジェクトはreturnステートメントを介して返されます。オブジェクトがreturnステートメントを介して返される場合、現時点でプログラムは、オブジェクトが将来使用されるかどうかは不明であり、外部スレッドがこの変数にアクセスでき、オブジェクトはこの時点でエスケープされます。

次のコードを使用して、この現象を表すことができます。

/**
 * @author binghe
 * @description 对象逃逸示例2
 */
public class ObjectReturn{
    
    
    public User createUser(){
    
    
        User user = new User();
        return user;
    }
}

2つの例があれば、JVMエスケープ分析について少し理解していると思います。そうです。JVMは、エスケープ分析を通じて新しいオブジェクトの使用範囲を分析し、新しいオブジェクトをヒープに割り当てる必要があるかどうかを判断できます。
ここに画像の説明を挿入

まだ終わっていないので、エスケープ分析の利点を見ていきましょう。そうすれば、友人はエスケープ分析をよりよく理解できます。

エスケープ分析の利点

エスケープ分析の利点は、一般に3つに分けることができます。オブジェクトはスタックに割り当てることができ、オブジェクトの分離またはスカラー置換、および同期ロックの除去です。次の図を使用して表すことができます。
ここに画像の説明を挿入

オブジェクトはスタックに割り当てられます

JVMは、エスケープ分析を通じて新しいオブジェクトの使用範囲を分析し、スタックにオブジェクトを割り当てる場合があります。スタック割り当てでは、ヒープスペースにオブジェクトを割り当てる必要がなく、スタックフレーム上のオブジェクトをすばやく作成および破棄できます。これにより、JVMガベージコレクションの負荷を効果的に軽減できます。

個別のオブジェクトまたはスカラー置換

JVMがエスケープ分析を通じてオブジェクトがスタックに割り当てられると判断した場合、ジャストインタイムコンパイルはオブジェクトを分割し、オブジェクトを小さなローカル変数で置き換えることができます。この分割プロセスをスカラー置換と呼びます。オブジェクトをローカル変数に置き換えた後、スタックに簡単に割り当てることができます。

ゲンロック除去

JVMが、エスケープ分析を通じて1つのスレッドからのみオブジェクトにアクセスできることを検出した場合、このオブジェクトにアクセスするときに同期ロックを追加する必要はありません。プログラムで同期ロックが使用されている場合、JVMは同期ロックを排除します。

ここで、この状況は同期ロックを目的としていることに注意してください。ロックロックの場合、JVMはロックを排除できません。

同期の削除を有効にするには、-XX:+ EliminateLocksパラメーターを追加する必要があります。このパラメーターはエスケープ分析に依存するため、-XX:+ DoEscapeAnalysisオプションを同時にオンにする必要があります。

したがって、すべてのオブジェクトと配列がヒープに割り当てられるわけではありません。ジャストインタイムコンパイルが存在するため、JVMが一部のオブジェクトにエスケープメソッドがないことを検出すると、スタックへの割り当てに最適化される可能性があります。

おすすめ

転載: blog.csdn.net/l1028386804/article/details/108721747