この写真は、JVMに少しでも触れたことがある人なら誰でも知っているはずです。これは、JVMを始めるための最初のレッスンであると言えます。中でも、「ヒープ」と「仮想マシンスタック(スタック)」はさらに馴染みがあります。以下、この図をもとにJVMのランタイムデータ領域を簡単に紹介します。
プログラムカウンター (プログラムカウンターレジスター)
これは、コンピューターオペレーティングシステムのプログラムカウンターに似ており、プログラムカウンターは次の命令のアドレスを表します。 JVM のプログラム カウンターの場合、現在のスレッドによって実行されるバイトコードの行番号インジケーターとして見ることができます (これは簡単に理解できます。各スレッドは次のようになります)。タスクの実行、スレッド切り替え後に正しい位置に復元できることを確認する必要がある場合)、重要な点 ——プログラム カウンター、これは JVM 仕様の中で唯一、そうでないものです。 OutOfMemory(メモリリーク、以下OOMの領域と呼ぶ)が発生することを規定しています。つまり、上の写真の残りの4エリアがOOMを引き起こす可能性があります。
☆仮想マシン スタック (Java 仮想マシン スタック)
このメモリ領域は、変数を保存するために使用されることが知られているように、私たちがよく呼ぶものです"スタック"つまり、例:
int i = 0;
仮想マシンのスタックメモリは、i変数を保存するために4バイトを使用します。変数のメモリ空間は最初から決まっているので(参照変数の場合はもちろんアドレス参照が格納されており、そのサイズも固定です)、このメモリ領域はコンパイラが決めることができます。 StackOverflowError または OOM エラー。 JVMパラメータ「-Xss228k」(スタックサイズは228k)を設定します。
これは終了条件なしの再帰です。実行結果は下図のようになります。JVMはStackOverflowErrorをスローします。これは、スレッドによって要求されたスタックの深さがで許可されている深さを超えていることを意味します。 JVM。
シングルスレッドの状況では、とにかく StackOverflowError がスローされます。 OOM 例外がスローされた場合、その理由は、メモリが使い果たされるまでスレッドが作成され続けるためです。
JVMのメモリは、ヒープメモリ+メソッド領域メモリ+残りメモリ、つまりに割り当てられたメモリで構成されますオペレーティングシステムによる - ヒープメモリ - メソッド領域メモリ。 -Xssは、各スレッドのスタック容量を設定します。これは、作成できるスレッドの数=残りメモリ/スタックメモリを意味します。このとき、スタックメモリが大きいと作成できるスレッド数は少なくなり、スタックメモリが小さいと作成できるスレッド数はOOMが発生しやすくなります。大きくなり、OOMは起こりにくくなります。 この状況を回避する最善の方法は、ヒープ メモリ+
メソッド領域のメモリを減らすか、スタック メモリを適切に減らすことです。スタックメモリの構成には、通常、デフォルト値1Mが使用されるか、64ビットのオペレーティングシステムと64ビットのJVMが使用されます。 ネイティブ メソッド スタック (
ネイティブ メソッド スタック) 違いは、仮想マシン スタックが Java
メソッドを提供することです。ローカル メソッド スタックが提供するのはNative メソッドです。 HotSpot 仮想マシンの実装では、ローカル メソッド スタックと仮想マシン スタックが 1 つに結合され、同様に StackOverflowError 例外と OOM 例外もスローされます。
☆Javaヒープ 对于堆,Java程序员都知道对象实例以及数组内存都要在堆上分配。堆不再被线程所独有而是共享的一块区域,它的确是用来存放对象实例,也是垃圾回收GC的主要区域。实际上它还能细分为:新生代(Young Generation)、老年代(Old Generation)。对于新生代又分为Eden空间、From Survivor空间、To Survivor空间。至于为什么这么分,这涉及JVM的垃圾回收机制,在这里不做叙述。堆同样会抛出OOM异常,下面例子设置JVM参数” -Xms20M -Xmx20M“(前者表示初始堆大小20M,后者表示最大堆大小20M)。 执行的结果可以清楚地看到堆上的内存空间溢出了。 ☆方法区(Method Area) 对于JVM的方法区,可能听得最多的是另外一个说法——永久代(Permanent Generation),呼应堆的新生代和老年代。方法区和堆的划分是JVM规范的定义,而不同虚拟机有不同实现,对于Hotspot虚拟机来说,将方法区纳入GC管理范围,这样就不必单独管理方法区的内存,所以就有了”永久代“这么一说。方法区和操作系统进程的正文段(Text Segment)的作用非常类似,它存储的是已被虚拟机加载的类信息、常量(从JDK7开始已经移至堆内存中)、静态变量等数据。现设置JVM参数为”-XX:MaxPermSize=20M”(方法区最大内存为20M)。 実際、上記のコードはJDK6、JDK7、JDK8で実行結果が異なります。その理由は、文字列定数プールが JDK6 のメソッド領域 (永続生成) に格納されているため、OutOfMemoryError:Permanent Space がスローされ、JDK7 の後に文字列定数がスローされるためです。プールは Java ヒープに移動されました。上記のコードは、ヒープ メモリが 20M に変更された場合、OutOfMemoryError:Java をスローします。ヒープスペース; JDK8 に関しては は単にメソッド領域の概念をキャンセルし、それを "metaspace (Metaspace)" に置き換えたので、JDK8 では仮想マシンのパラメーター "-XX:MaxPermSize" には意味がなく、"-XX:MetaspaceSize" や "-XX:MaxMetaspaceSize" などに置き換えられます。 1 package com.jvm; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * -Xms20M -Xmx20M 堆初始大小20M 堆最大大小20M 8 * Created by yulinfeng on 7/11/17. 9 */10 public class Test {11 12 public static void main(String[] args) {13 List<Test> list = new ArrayList<Test>();14 int count = 0;15 try {16 while (true) {17 count++;18 list.add(new Test()); //不断创建线程19 }20 } catch (Throwable e) {21 System.out.println("创建实例个数:" + count);22 e.printStackTrace();23 }24 25 }26 }
1 package com.jvm; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * -XX:MaxPermSize=20M 方法区最大大小20M 8 * Created by yulinfeng on 7/11/17. 9 */10 public class Test {11 12 public static void main(String[] args) {13 List<String> list = new ArrayList<String>();14 int i = 0;15 while (true) {16 list.add(String.valueOf(i++).intern()); //不断创建线程17 }18 }19 }
以上がJVM の基礎の概要: ランタイム データ領域の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。