ランタイムデータ領域
《深入理解Java虚拟机》(第二章 Java内存区域与内存溢出异常)
それは別のデータ領域の数を管理しますれているJavaプログラムの実行中のJava仮想マシンのメモリ部門。これらの領域は、独自の目的を持って、創造と破壊の時間は、仮想マシンプロセスと一緒にいくつかの領域が存在し、一部の地域では、スレッド間を作成し、破壊するために、開始と終了のユーザーに依存しています。
「Java仮想マシン仕様(Java SEのバージョン7)」の要件によると、Java仮想マシンのメモリ管理は、以下のランタイム・データ領域が含まれます。
まず、プログラムカウンタ
プログラムカウンタが小さいメモリ空間で、彼は現在の実行スレッドのインジケータバイトコードの行番号として見ることができます。仮想マシンの概念モデルで(
仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现
)、バイトコードインタプリタは、次に実行すべき命令を選択するためのコード、バイトカウンタの値を変更することで、分岐、ループ、分岐、例外処理、回収、その他の基本的なスレッドを働いているとき機能は完全にカウンターに依存する必要があります。
マルチスレッドJava仮想マシンが順番にあるので、プロセッサは、(aが決定される任意の時点で、切り替えてスレッドによるプロセッサ実行時間の割り当てが達成するために
对于多核处理器来说是一个内核
)だけの命令の1つのスレッドを実行します。したがって、正しい実行位置にスレッドスイッチを復元するために、各スレッドは、別のプログラムカウンタを必要とする、カウンタ独立スレッド間で互いに独立店舗を、我々は「ためのメモリ領域のこのタイプを呼び出すスレッドプライベート」でメモリ。
スレッドは、Javaメソッドを実行している場合、カウンタは、実行中の仮想マシンのバイトコード命令のアドレスを記録し、この方法は、ネイティブに実行されている場合、このカウンタの値がヌル(未定義)です。このメモリ領域は、地域のOutOfMemoryError Java仮想マシン仕様でどのような状況のために用意されていませ唯一のものです。
二、Java仮想マシン・スタック
プログラムカウンタと同じように、Java仮想マシンのスレッドスタックは、プライベートでそのライフサイクルと同じスレッド。
Javaメモリー・モデル記載の方法を行う仮想マシンのスタックがある:店舗情報ローカル変数テーブル、オペランドスタック、動的リンク、方法輸出するために使用されるスタックフレームの実行中に各メソッドが作成されます。実行手順が完了するまで各方法は、スタックにスタックから仮想マシンのスタックに、対応するスタックフレーム処理と呼ばれています。
私たちは、多くの場合、Javaのヒープメモリとスタックメモリに、タスクはビットラフであったこと。
ここで、「スタック」今、仮想マシンのスタックについて話しています。または仮想マシン・スタック、ローカル変数テーブルセクション。
ローカル変数テーブルのための記憶されたのコンパイル知られている様々な基本的なデータ・タイプ(
boolean、byte、char、short、int、float、long、double
)、オブジェクト参照(refrence类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置
)とRETURNADDRESSタイプ(指向了一条字节码指令的地址
)。
Java仮想マシン仕様では、このエリアには2つの異常を提供しています。
スタックは、スレッドの深さよりも大きい仮想マシンの許容深さによって要求された場合にStackOverflowErrorが例外をスローします。
仮想マシンが動的に(スタックを展開することができた場合
当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈
)、拡張場合は、十分なメモリに適用することはできません、OutOfMemoryErrorがスローされます。
第三に、ネイティブメソッドスタック
ネイティブメソッドスタックおよびスタックの仮想マシンの役割は、それらの間に、非常に似ているとの違いだけで、仮想マシンのスタック方法(実行するJava仮想マシン用
也就是字节码
)サービス、およびローカルスタック方法があるネイティブサービスの方法に仮想マシンを使用します。
ネイティブメソッドの方法で使用される言語のスタック、および使用するデータ構造は、仮想マシンの仕様、特定の仮想マシンでは必須ではありませんので、それを実装する自由。でも、いくつかの仮想マシンは、(
譬如Sun HotSpot虚拟机
)に直接1つのネイティブメソッドスタックおよびスタックの仮想マシンに入れました。
仮想マシンのスタックのように、ネイティブメソッドではStackOverflowErrorがスタックし、OutOfMemoryErrorがスローされます。
四、Javaのヒープ
ほとんどのアプリケーションでは、Javaヒープメモリは、Java仮想マシン管理の最大の作品です。仮想マシンの起動時にヒープメモリ領域内のすべてのスレッドで共有されているJavaが作成されます。このメモリ領域の唯一の目的はされて、オブジェクトのインスタンスを格納し、ほぼすべてのオブジェクトインスタンスがメモリを割り当てるためにここにいます。
这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也就渐渐变得不是那么“绝对”了。
Javaヒープは、ガベージコレクタによって管理されるメインエリアであるため、多くの場合とも呼ばれる「GCヒープ。」
集電体による視野のメモリリカバリポイントは、基本的に使用しているの観点から世代コレクションアルゴリズムを Javaヒープはまたに分けることができますので、:新しい世代と古い年、その後、少し詳しく説明エデンスペースがサバイバースペースにSurvirorからは、そこにあります宇宙のように。ビューのメモリ割り当て点の観点から、Javaヒープのスレッドで共有は、複数のスレッドプライベート割り当てられたバッファに分割することができます。しかし、分割どのような場合には、更なる目的は、より良いメモリの回復、またはより高速なメモリ割り当てにある分割に関係なく、エリア、まだ保存されているオブジェクトインスタンスの、コンテンツの保存とは何の関係もありません。
Java仮想マシンの仕様では、Javaのヒープは、私たちのディスクスペースのような、に限り、論理的に連続、不連続な物理メモリ空間であってもよいです。実装は、いずれかの固定サイズに実装することができる場合、それはまた、拡張することができるが、現在主流の仮想マシンは、スケーラブル(に従って実装されています
通过-Xmx和-Xms控制
)。そこにヒープメモリの割り当てには完全な例ではなく、スタックはもはや広げることができれば、それがスローされますOutOfMemoryErrorの例外を。
第五に、メソッド領域
メソッド領域とヒープ、それぞれあるスレッドの共有メモリ領域、彼は店のために使用されるクラスの情報を仮想マシンにロードされている、定数は、静的変数は、タイムコンパイラは、コードや他のコンパイルするデータを。Java仮想マシン仕様のメソッド領域は、ヒープの論理的な部分として説明したが、彼はという別名持っていたされているが非ヒープ(非ヒープ)を、目的は、Javaヒープは区別されるべきです。
HotSpot仮想マシンの開発者で癖のために、デプロイプログラムへの開発者、多くの人々は、本質的に、両者は同等ではない、という理由だけのHotSpot仮想マシンのデザインチーム「Permanent世代」と呼ばれる方法領域へのより喜んでいますGC世代収集領域は、方法に及ぶ、またはホットスポットのガベージコレクタは、メモリ管理の一環として、このようなJavaヒープを管理できるようにする方法は、唯一の永久的な世代の領域を達成するために選択し、メモリ管理方式エリアのために特別に書かれたコードを省略することができます作品。他の仮想マシン(のため
如BEA JRockit、IBM J9等
)永久世代の概念が存在しないです。
原則的には、面積が制約なく、仮想マシン、仮想マシンの仕様の詳細を実装する方法方法に属しているが、世代は永久的なメソッド領域を達成するために、それはので、それは、良いアイデアではないと思われる可能性が高い経験メモリオーバーフローの問題にあります(
永久代有-XX:MaxPermSize的上限,J9和JrockIT只要没有触碰到进程可用内存的上限,例如32位系统中的4GB,就不会出现问题
)、非常に少数の方法は(ある如String.intern()
ため、このような理由により、異なる仮想マシンで異なる症状があります)。したがって、HotSpot仮想マシンのための、ロードマップが発表公式情報によると、今では恒久的な世代を放棄しなければならないと徐々にの使用によって置き換えられネイティブメモリ地区計画方法を実装するために、およびJDK1.7のHotSpotがリリースされている中で、それはもともとされています永久に代わって、文字列定数プール取り除きます。
法上のJava仮想マシン仕様の制限は非常に加えて、面積を緩和し、Javaヒープメモリなどの連続を選択してサイズを固定または拡張することができるが、また、ガベージコレクションを実装しないことを選択することができますすることができます必要はありません。
対照的に、この領域のガベージコレクションの動作は比較的小さい外観が、ちょうど同じ名前の生成の永久方法として地域にないデータ「永久」が存在します。ガベージコレクションの対象この領域は、リサイクルや一定のプール型のアンロードのために主にある条件が非常に厳しいことができ、荷降ろしの特にクラス、一般的には、地域の回復は、「成果」は比較的不十分ではなく、地域のこの部分回復は確かに必要です。BUG日は、企業のリストには、深刻なバグの数は完全にメモリリークによって引き起こされるこのエリアには回収されないのHotSpot仮想マシンの低いバージョンによるものであるがありました。
Java仮想マシンの仕様では、メモリ割り当て領域の方法は、需要を満たすことができない場合、スローされますOutOfMemoryErrorの例外を。
ランタイム定数プール
実行時定数プールは、ゾーン法の一部。クラス、フィールド、メソッド、およびインターフェース記述情報に加えて、クラス・ファイルのバージョン、ならびに定数プール情報、種々のリテラルを格納し、生成した符号をコンパイルするために、この部分は、クラスをロードします多くの場合、プールボリュームストレージの方法領域に実行します。
ランタイム定数プールエリアは方法の一部であるため、定数プールは、もはや時にメモリにスローされるように適用することができたときに、自然な方法は、メモリ領域によって制限されていないのOutOfMemoryErrorの例外。
ダイレクトメモリ
ダイレクトメモリ(ダイレクト・メモリ)が稼働している仮想マシンのデータ領域の一部ではない、またそれは仕様で定義されたJava仮想マシンのメモリ領域です。しかし、このメモリは、頻繁に使用され、私たちはここで説明するために一緒に入れても、OutOfMemoryErrorの例外につながる可能性があります。
JDK 1.4の導入に基づいて、新たに追加されたNIO(新しい入力/出力)タイプにチャンネル(チャンネル)及びバッファー(緩衝液) I / Oモードでは、それは、次に、直接外部ヒープメモリが割り当てられたネイティブライブラリを使用することができ動作させるための基準としてのJava DirectByteBufferにこのメモリをオブジェクトのスタックを格納することによって。Javaのヒープヒープとネイティブにレプリケートされたデータの前後にを避けるために、これはかなりいくつかのシナリオでは、パフォーマンスを向上させることができます。
もちろん、マシンに直接割り当てられたメモリは、メモリは間違いなく、まだだろうがあるため、Javaヒープのサイズによって限定されるものではなく、ネイティブ総メモリ(
包括RAM以及SWAP区或者分页文件
スペースアドレッシング)サイズと処理の制限を。サーバ管理者の仮想マシンの構成のような実際のメモリ-Xmx設定パラメータ情報に基づいてパラメータが、アプローチは、各領域が物理メモリの制限(の和よりも大きくなるように直接メモリを無視したとき包括物理的和操作系统级的限制
のOutOfMemoryError動的拡張をもたらします)。
概要
データ領域 | データの種類 | スレッド | 機能 |
---|---|---|---|
まず、プログラムカウンタ | スレッドプライベート | ||
二、Java仮想マシン・スタック | ローカル変数テーブル、スタック操作基、動的リンク、方法輸出の数 | スレッドプライベート | Java仮想マシン(バイトコード)サービスの実施のための |
ローカル変数テーブル | 基本データ型、オブジェクト参照、RETURNADDRESSタイプをコンパイル(アドレスバイトコード命令) | ||
第三に、ネイティブメソッドスタック | スレッドプライベート | 仮想マシンのメソッドネイティブサービスのために使用するには | |
第四に、ヒープ | Objectインスタンス | スレッドシェア | メモリ内に作成するときの最大の作品は、仮想マシンが起動 |
第五に、メソッド領域 | クラス情報は、定数などの静的変数、コンパイルされたコードを、ロードされました | スレッドシェア | 論理ヒープの一部、メインメモリを回収し、クラスの定数プールをアンロードするための |
ランタイム定数プール | リテラルと記号参照の多様性を生成するコンパイル | メソッド領域の一部 | |
ダイレクトメモリ | JDK 1.4が新たNIOに参加し、ネイティブ関数は、直接チャネルに基づいて使用することができ、バッファが参照としてこのメモリのDirectByteBuffer Javaヒープオブジェクトによって操作、ヒープメモリの外側を割り当て | いくつかのシナリオが大幅にパフォーマンスを向上させるコピーJavaヒープとスタックデータ先住民の間で前後を避けるために |