この記事は JVM エスケープに関するものですか? JVM エスケープ分析の原理の紹介は、必要な方に参考にしていただけると幸いです。
Java のオブジェクトはデフォルトでヒープに割り当てられ、呼び出しスタックにはオブジェクトのポインタのみが保存されることは誰もが知っています。オブジェクトが使用されなくなった場合は、参照ツリーを走査してメモリを再利用するために GC を利用する必要があります。ヒープ内のオブジェクトが多すぎると、オブジェクトのリサイクルとメモリの整理に大きな負荷がかかり、パフォーマンスに影響します。したがって、日々の開発においては、メモリと時間が非常に貴重であり、スタックのオーバーヘッドをいかに最適化するかが比較的重要な問題となります。
ここでは、エスケープ分析の観点から JVM の最適化について説明します。
なぜ「Escape」
コンピュータ言語コンパイラ最適化の原理では、エスケープ解析とはポインタのダイナミック レンジを解析する方法を指します。コンパイラの最適化原則がポインタ解析とシェイプ解析に関連しているのと同じです。変数 (またはオブジェクト) がメソッドに割り当てられると、そのポインターがグローバルに返されたり参照されたりすることがあります。この現象は、ポインター (または参照) エスケープと呼ばれます。平たく言えば、オブジェクトのポインターが複数のメソッドまたはスレッドによって参照される場合、それをオブジェクトのポインター (またはオブジェクト) のエスケープと呼びます。
インターネット上のブロガーは、シンプルで直接的なコードを使用してこの方法でエスケープを説明しました。これは非常に簡単で参考にできると思います。
public StringBuilder escapeDemo1(System a, System b) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(a); stringBuilder.append(b); return stringBuilder; }
stringBuilder は、メソッドとこのメソッドが直接返された場合、stringBuilder は他のメソッドやパラメータによって変更される可能性があるため、スコープはローカル変数ですが「エスケープ」されます。
次に、コードを変更します。
public String escapeDemo2(System a, System b) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(a); stringBuilder.append(b); return stringBuilder.toString(); }
このようにすると、StringBuilder は返されず、toString() が返されます。この場合、StringBuilder はメソッドから直接分離されず、エスケープは発生しません。
エスケープ分析とは
エスケープ分析は、Java プログラムにおける同期負荷とメモリ ヒープ割り当てのプレッシャーを効果的に軽減できる機能横断的なグローバル データ フローです。分析アルゴリズム。 Java ホットスポット コンパイラは、エスケープ分析を通じて、新しいオブジェクトの参照の使用範囲を分析し、このオブジェクトをヒープに割り当てるかどうかを決定できます。エスケープ分析は現在、Java 仮想マシンにおける比較的最先端の最適化テクノロジです。
エスケープ解析の原理
一時的なメモリの割り当てを減らすための、Java 自体の制限 (オブジェクトはヒープにしか配置できない) は理解できます。ヒープ内のオブジェクト数。メソッド本体にローカル変数を定義します。この変数は、メソッドの実行中にエスケープされません。JVM チューニング メカニズムに従って、クラスのインスタンスが最初にヒープ内に作成されます。その後、このオブジェクトの参照が呼び出しスタックにプッシュされ、実行を継続します。これは、JVM 最適化の前の方法です。次に、エスケープ分析を使用して JVM を最適化します。つまり、スタックの再割り当て方法では、まずエスケープされていない変数を見つけ、その変数をヒープに入れずにスタックに直接格納します。最後に、スレッドの実行のためにスタックを呼び出し続けます。終了すると、スタック領域がリサイクルされ、ローカル変数もリサイクルされます。この操作は、最適化前はヒープ内にあり、最適化後はスタック内にあるため、ヒープ内のオブジェクトの割り当てと破棄が削減され、パフォーマンスが最適化されます。
エスケープ方法
メソッド エスケープ: メソッド本体で、メソッドに渡されるなど、外部メソッドによって参照されるローカル変数を定義します。呼び出しパラメータとして、またはオブジェクトとして直接返されます。あるいは、メソッドからオブジェクトが飛び出しているとも理解できます。
スレッド エスケープ: このオブジェクトは、インスタンス変数に割り当てられたり、他のスレッドによってアクセスされたりするなど、他のスレッドによってアクセスされます。オブジェクトは現在のスレッドからエスケープされました。
エスケープ分析の利点
オブジェクトがメソッド本体内またはスレッド内でエスケープしない場合 (またはエスケープ分析を通過した後にエスケープが発生しない場合) エスケープ)
1. スタック上の割り当て
一般に、スタック上のスペースが使用できる場合、エスケープされないオブジェクトは比較的大きなスペースを占めます。メソッドは最後に破棄され、GC プレッシャーが軽減されます。
2. 定義したクラスのメソッドに同期ロックがある場合、実行時には 1 つのスレッドのみがロックされます。アクセスすると、この時点では、エスケープ解析後のマシンコードは同期ロックなしで実行されます。
3. スカラー置換
Java虚拟机中的原始数据类型(int,long等数值类型以及reference类型等)都不能再进一步分解,它们可以称为标量。相对的,如果一个数据可以继续分解,那它称为聚合量,Java中最典型的聚合量是对象。如果逃逸分析证明一个对象不会被外部访问,并且这个对象是可分解的,那程序真正执行的时候将可能不创建这个对象,而改为直接创建它的若干个被这个方法使用到的成员变量来代替。拆散后的变量便可以被单独分析与优化,可以各自分别在栈帧或寄存器上分配空间,原本的对象就无需整体分配空间了。
开启设置
在JDK 6u23以上是默认开启,这里将设置重新明确一下:
强制开启:
-server -XX:+DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m
关闭逃逸分析:
-server -XX:-DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m
写在结尾
栈上的空间一般而言是非常小的,只能存放若干变化和小的数据结构,无法存储大容量数据。目前的实现都是采用不那么准确但是时间压力相对较小的算法来完成逃逸分析,这就可能导致效果不稳定。所以,逃逸分析的效果只能在特定场景下,满足高频和高数量的小容量的变量分配结构,才是合适的。
以上がJVMエスケープとは何ですか? JVM エスケープ分析の原理の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。