Java虚拟机运行时数据区(JVM_2)

时间:2021-06-14 01:25:40

2.3 运行时数据区(Run-TIme Data Areas)

2.3.1 官网概括

官网; https://docs.oracle.com/javase/specs/jvms/se8/html/index.html

The Java Virtual Machine defines various run-time data areas that are used during 
execution of a program. Some of these data areas are created on Java Virtual 
Machine start-up and are destroyed only when the Java Virtual Machine exits. 
Other data areas are per thread. Per-thread data areas are created when a thread 
is created and destroyed when the thread exits.

2.3.2 图解

Java虚拟机运行时数据区(JVM_2)

2.3.3 初步介绍

2.3.3.1 Method Area(方法区)

Java虚拟机运行时数据区(JVM_2)

1.  Java虚拟机有一个在所有Java虚拟机线程之间共享的方法区域。

2.  方法区域是在虚拟机启动时创建的。

3.  方法区域在逻辑上是堆的一部分,但是它有一个别名Non-Heap(非堆),目的是和heap(堆)分开

4.  方法区域的内存不需要是连续的。

5.  如果方法区域中的内存不能用于满足分配请求,Java虚拟机将抛出OutOfMemoryError。

另外不同JDK版本Method Area真正的实现不同;

JDK 8中 是Metaspace(元空间)

JDK 8之前是Perm Space(永久代)

二者主要区别:

Meta space和Perm space的主要区别在于存储元数据的方式和管理方式。Meta space使用本地内存存储元数据,并具有自动内存管理功能,而Perm space则位于JVM的堆内存中,并且容量是固定的。

2.3.3.2 Heap(堆)

Java虚拟机运行时数据区(JVM_2)

1.  Java堆是Java虚拟机所管理内存中最大的一块,在虚拟机启动时创建,被所有线程共享。

2.  Java对象实例以及数组都在堆上分配。

2.3.3.3 Java Virtual Machine Stacks(虚拟机栈)

Java虚拟机运行时数据区(JVM_2)

1.  虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。换句话说,一个Java线程的 运行状态,由一个虚拟机栈来保存,所以虚拟机栈肯定是线程私有的,独有的,随着线程的创建而创 建。

2.  每一个被线程执行的方法,为该栈中的栈帧,即每个方法对应一个栈帧。调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。

void method_a(){
method_b();
}
void method_b(){
method_c();
}
void method_C(){
}

Java虚拟机运行时数据区(JVM_2)

栈帧:

官网https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6

每个栈帧对应一个被调用的方法,可以理解为一个方法的运行空间。 每个栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向运行时常量池的引用(A reference to the run-time constant pool)、方法返回地址(Return Address)和附加信息。

Java虚拟机运行时数据区(JVM_2)

局部变量表: 方法中定义的局部变量以及方法的参数存放在这张表中 局部变量表中的变量不可直接使用,如需要使用的话,必须通过相关指令将其加载至操作数栈中作为操作数使 用。

操作数栈:以压栈和出栈的方式存储操作数的

动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用 过程中的动态连接(Dynamic Linking)。

方法返回地址:当一个方法开始执行后,只有两种方式可以退出,一种是遇到方法返回的字节码指令;一种是遇 见异常,并且这个异常没有在方法体内得到处理。

2.3.3.4 The pc Register(程序计数器)

Java虚拟机运行时数据区(JVM_2)

如果线程正在执行Java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是Native方法,则这个计数器为空。

2.3.3.5 Native Method Stacks(本地方法栈)

Java虚拟机运行时数据区(JVM_2)

如果当前线程执行的方法是Native类型的,这些方法就会在本地方法栈中执行。

那如果在Java方法执行的时候调用native的方法呢?

Java虚拟机运行时数据区(JVM_2)

2.3.4 各种情况

2.3.4.1 栈指向堆

在栈帧中有一个变量,类型为引用类型,比如Object obj=new Object(),这时候就是典型的栈中元 素指向堆中的对象。

Java虚拟机运行时数据区(JVM_2)

2.3.4.2 方法区指向堆

方法区中会存放静态变量,常量等数据。如果是下面这种情况,就是典型的方法区中元素指向堆中的对 象。

private static Object obj=new Object();

Java虚拟机运行时数据区(JVM_2)

2.3.4.3 堆指向方法区

方法区中会包含类的信息,堆中会有对象,那怎么知道对象是哪个类创建的呢?

Java虚拟机运行时数据区(JVM_2)

那么一个对象具体是怎么知道它是由那个类创建出来的呢?这就涉及到对象的内存模型了。

2.3.4.4 Java对象内存模型

Java虚拟机运行时数据区(JVM_2)