ホームページ  >  記事  >  Java  >  Java メモリ領域とメモリ オーバーフロー例外の詳細な紹介

Java メモリ領域とメモリ オーバーフロー例外の詳細な紹介

零下一度
零下一度オリジナル
2017-06-25 10:58:351426ブラウズ

Javaメモリ領域とメモリオーバーフロー例外

1.ランタイムデータ領域

1.プログラムカウンタ:スレッドプライベート、現在実行されている命令の場所を保存するために使用されます

2.Java仮想マシンスタック:スレッドプライベート、Java メソッド実行モデルを記述します。メソッドを実行すると、ローカル変数、基本型変数、参照、その他の情報を保存するためにスタック フレームが作成されます

3. Java ネイティブ メソッド スタック: スレッド プライベート、によって使用されるネイティブ メソッドを提供します。仮想マシン

4. Java ヒープ: スレッドによって共有され、ガベージ コレクターの主な作業場所です。オブジェクト インスタンスなどを格納します。

5. メソッド領域: スレッドによって共有され、クラス情報、定数、静的変数、など

実行時定数: コンパイル用に保存

6. ダイレクトメモリ: マシンメモリ

2. 仮想マシンオブジェクト

1. オブジェクトの作成

  • まず、定数プールがあるかどうかを確認しますそのようなシンボルの参照を見つけて、クラスがロードおよび初期化されているかどうかを確認できます。そうでない場合は、ロードプロセスを最初に実行する必要があります。

  • オブジェクトにメモリを割り当てます。スペースを計算し、ヒープから連続領域または不連続領域を分割します。スレッド安全性の問題を回避するには、cas+failure retry を使用します (オブジェクトが非常に頻繁に作成されるため、現在のメモリが割り当てられているかどうかはわかりません)

  • メモリ空間の初期化: 割り当てられたメモリ空間を 0 の値に初期化します

  • オブジェクトの基本情報を設定します: メタデータ、ハッシュコード、gc など。

  • Java init 初期化を実行します:

2. オブジェクトのメモリレイアウト

オブジェクトヘッダー: オブジェクトのハッシュコードを保存し、ロックしますステータスなどと型ポインタ(オブジェクトが指すクラスのメタデータ)

インスタンスデータ:オブジェクトが実際に格納している情報

アライメント塗りつぶし:ルールに則った塗りつぶし

3. オブジェクトの配置にアクセスする

オブジェクトへのアクセスは、Javaスタック上の参照データを通じて、オブジェクトへの参照を維持します

アクセス方法: ハンドルとダイレクトアクセス

' ハンドル: ハンドル プールはヒープ内に維持されます。参照はハンドルを指し、ハンドルにはオブジェクトのインスタンス データと型データのアドレス情報が含まれています

ハンドル内のインスタンス データを移動したり、直接変更したりするのは簡単です。それだけです。コストがかかるので、ポインターの位置をもう 1 つ

Direct:参照はオブジェクトアドレスを直接指します

三、実戦OutofMemoryERROR

1. java heap overflow

パラメータ

:-Xms heap smallest Value;- :-Xssはスタック値を設定します

スタックの深さは、無限再帰または多数のスレッドの作成によって増加します

//递归来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. メソッド領域と定数プールのオーバーフロー

パラメータ

: -XX:PermSize メソッド領域のサイズ ;-XX: MaxPermSize メソッド領域の最大サイズ

JDK1.6より前は、大量のStringを作成することができ、仮想マシンはオブジェクトをコピーして定数プールに入れ、オーバーフローを引き起こしていました

1.7以降ではこれは許可されていません, なぜなら、仮想マシンは、オブジェクトが最初に定数プールに現れたときにのみオブジェクトへの参照を保存するからです

メソッド領域のオーバーフロー: メソッド領域はクラス情報を保存しますが、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:永続世代へ

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);
    }
}

このコードを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 による。

str2 の比較は false を返します。文字列「java」は StringBuilder.toString() を実行する前にすでに出現しており、文字列定数プール内にそれへの参照がすでに存在しており、「初出」の原則に準拠していないためです。 , and " 「Computer Software」という文字列は初めて出現するので true を返します

注: 1.7 以降では、初めて出現する参照を保存します。上記の分析を理解してください

4. ネイティブ ダイレクト メモリ

パラメータ: -XX : MaxDirectMemorySize ダイレクトメモリサイズ; デフォルト == 最大ヒープメモリ

以上がJava メモリ領域とメモリ オーバーフロー例外の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。