1.プログラムカウンタ:スレッドプライベート、現在実行されている命令の場所を保存するために使用されます
2.Java仮想マシンスタック:スレッドプライベート、Java メソッド実行モデルを記述します。メソッドを実行すると、ローカル変数、基本型変数、参照、その他の情報を保存するためにスタック フレームが作成されます
3. Java ネイティブ メソッド スタック: スレッド プライベート、によって使用されるネイティブ メソッドを提供します。仮想マシン
4. Java ヒープ: スレッドによって共有され、ガベージ コレクターの主な作業場所です。オブジェクト インスタンスなどを格納します。
5. メソッド領域: スレッドによって共有され、クラス情報、定数、静的変数、など
実行時定数: コンパイル用に保存
6. ダイレクトメモリ: マシンメモリ
まず、定数プールがあるかどうかを確認しますそのようなシンボルの参照を見つけて、クラスがロードおよび初期化されているかどうかを確認できます。そうでない場合は、ロードプロセスを最初に実行する必要があります。
オブジェクトにメモリを割り当てます。スペースを計算し、ヒープから連続領域または不連続領域を分割します。スレッド安全性の問題を回避するには、cas+failure retry を使用します (オブジェクトが非常に頻繁に作成されるため、現在のメモリが割り当てられているかどうかはわかりません)
メモリ空間の初期化: 割り当てられたメモリ空間を 0 の値に初期化します
オブジェクトの基本情報を設定します: メタデータ、ハッシュコード、gc など。
Java init 初期化を実行します:
オブジェクトヘッダー: オブジェクトのハッシュコードを保存し、ロックしますステータスなどと型ポインタ(オブジェクトが指すクラスのメタデータ)
インスタンスデータ:オブジェクトが実際に格納している情報
アライメント塗りつぶし:ルールに則った塗りつぶし
オブジェクトへのアクセスは、Javaスタック上の参照データを通じて、オブジェクトへの参照を維持します
アクセス方法: ハンドルとダイレクトアクセス
' ハンドル: ハンドル プールはヒープ内に維持されます。参照はハンドルを指し、ハンドルにはオブジェクトのインスタンス データと型データのアドレス情報が含まれていますハンドル内のインスタンス データを移動したり、直接変更したりするのは簡単です。それだけです。コストがかかるので、ポインターの位置をもう 1 つ
Direct:参照はオブジェクトアドレスを直接指します
三、実戦OutofMemoryERROR
1. java heap overflow
パラメータ
//递归来StackOverFlowerpublic class JavaVMStackSOF {private int stackLength = 1;public void stackLeak(){ stackLength++; stackLeak(); }public static void main(String[] args)throws Throwable{ JavaVMStackSOF oom = new JavaVMStackSOF();try { oom.stackLeak(); } catch(Throwable e){ System.out.println("stack length:" + oom.stackLength);throw e; } } }3. メソッド領域と定数プールのオーバーフロー
パラメータ
JDK1.6より前は、大量のStringを作成することができ、仮想マシンはオブジェクトをコピーして定数プールに入れ、オーバーフローを引き起こしていました
メソッド領域のオーバーフロー: メソッド領域はクラス情報を保存しますが、For の動的クラスが大量に生成されることでオーバーフローします。たとえば、Spring は実際には動的プロキシによって生成されたクラス
public class JavaMethodAreaOOM{public static void main(String[]args){while(true){//创建大量的动态类,动态代理OOMObjectEnhancer enhancer=new Enhancer(); enhancer.setSuperclass(OOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor(){public Object intercept(Object obj,Method method,Object[]args,MethodProxy proxy)throws Throwable{return proxy.invokeSuper(obj,args); }} ); enhancer.create(); }}static class OOMObject{ } }
String.intern() を使用します。その機能は次のとおりです。文字列定数プールにこの String オブジェクトと等しい文字列が既に含まれている場合は、戻り値を返します。プール内の文字列を表す文字列。それ以外の場合、この String オブジェクトに含まれる文字列が定数プールに追加され、この String オブジェクトへの参照が返されます。永続世代)は別で、定数プールはメソッド領域内
JDK7:永続世代へ このコードをJDK 1.6で実行すると2つのfalseが得られますが、JDK 1.7で実行すると1つのtrueと1つのfalseが得られます。 違いの理由は次のとおりです。JDK 1.6 では、 intern() メソッドは最初に見つかった文字列インスタンスを永続世代にコピーし、永続世代の文字列インスタンスへの参照を返しますが、StringBuilder によって作成されたものは、 string インスタンスは Java ヒープ上にあるため、同じ参照であってはならず、false が返されます。 そして、JDK 1.7: intern() 実装はインスタンスをコピーしなくなり、定数プール内で最初に出現した のインスタンス参照のみを記録するため、 intern() によって返される参照は作成された文字列インスタンスと同じになります。 StringBuilder による。 注: 1.7 以降では、初めて出現する参照を保存します。上記の分析を理解してくださいpublic class RuntimeConstantPoolOOM{public static void main(String[]args){
String str1=new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern()==str1);
String str2=new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern()==str2);
}
}
パラメータ: -XX : MaxDirectMemorySize ダイレクトメモリサイズ; デフォルト == 最大ヒープメモリ
以上がJava メモリ領域とメモリ オーバーフロー例外の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。