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 图解
2.3.3 初步介绍
2.3.3.1 Method Area(方法区)
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(堆)
1. Java堆是Java虚拟机所管理内存中最大的一块,在虚拟机启动时创建,被所有线程共享。
2. Java对象实例以及数组都在堆上分配。
2.3.3.3 Java Virtual Machine Stacks(虚拟机栈)
1. 虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。换句话说,一个Java线程的 运行状态,由一个虚拟机栈来保存,所以虚拟机栈肯定是线程私有的,独有的,随着线程的创建而创 建。
2. 每一个被线程执行的方法,为该栈中的栈帧,即每个方法对应一个栈帧。调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。
void method_a(){
method_b();
}
void method_b(){
method_c();
}
void method_C(){
}
栈帧:
官网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)和附加信息。
局部变量表: 方法中定义的局部变量以及方法的参数存放在这张表中 局部变量表中的变量不可直接使用,如需要使用的话,必须通过相关指令将其加载至操作数栈中作为操作数使 用。
操作数栈:以压栈和出栈的方式存储操作数的
动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用 过程中的动态连接(Dynamic Linking)。
方法返回地址:当一个方法开始执行后,只有两种方式可以退出,一种是遇到方法返回的字节码指令;一种是遇 见异常,并且这个异常没有在方法体内得到处理。
2.3.3.4 The pc Register(程序计数器)
如果线程正在执行Java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是Native方法,则这个计数器为空。
2.3.3.5 Native Method Stacks(本地方法栈)
如果当前线程执行的方法是Native类型的,这些方法就会在本地方法栈中执行。
那如果在Java方法执行的时候调用native的方法呢?
2.3.4 各种情况
2.3.4.1 栈指向堆
在栈帧中有一个变量,类型为引用类型,比如Object obj=new Object(),这时候就是典型的栈中元 素指向堆中的对象。
2.3.4.2 方法区指向堆
方法区中会存放静态变量,常量等数据。如果是下面这种情况,就是典型的方法区中元素指向堆中的对 象。
private static Object obj=new Object();
2.3.4.3 堆指向方法区
方法区中会包含类的信息,堆中会有对象,那怎么知道对象是哪个类创建的呢?
那么一个对象具体是怎么知道它是由那个类创建出来的呢?这就涉及到对象的内存模型了。