JVM--运行时数据区内存模型
JVM--运行时数据区内存模型
jvm学习内容记录,运行时数据区概念定义、内存模型、以及结构分析。内容部分参考自Oracle官方网站和咕泡学院课件内容。版本基于jdk1.8。
@
run-time data areas
概念定义
从下列java virtual machine中关于run-time data areas的官方定义中可以得出,运行时数据区就是类文件被装载后,类中元数据信息、变量、常量、方法等信息存放的位置。
Run-Time Data Areas
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.
直译:Java虚拟机定义了在程序执行期间使用的各种运行时数据区域。其中一些数据区域是在Java虚拟机启动时创建的,只在Java虚拟机退出时销毁。其他数据区域为每个线程。每个线程数据区域在线程创建时创建,在线程退出时销毁。
内存模型结构
上图为运行时数据区的内存模型定义。接下来开始具体分析各个区域中的结构以及存储内容。
The PC Register
概念定义
首先看一下官网对于程序计数器的定义。
The
pc
RegisterThe Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own
pc
(program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is notnative
, thepc
register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread isnative
, the value of the Java Virtual Machine'spc
register is undefined. The Java Virtual Machine'spc
register is wide enough to hold areturnAddress
or a native pointer on the specific platform.
直译:Java虚拟机可以支持同时执行多个线程(JLS§17)。每个Java虚拟机线程都有自己的pc(程序计数器)寄存器。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法(§2.6)。如果该方法不是
native
的,则pc寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程当前执行的方法是native
的,那么Java虚拟机的pc寄存器的值是未定义的。Java虚拟机的pc寄存器足够宽,可以在特定平台上保存一个returnAddress或一个本机指针。
从官方定义中得出,java程序计数器用于记录每个线程
的正在执行的java虚拟机指令的地址,也就是线程执行到方法的哪个地方了,以便CPU时间片切换后还能恢复到正确的执行位置。
而对于程序计数器而言,只会记录java方法的字节码指令地址,并不会记录native
的。
Java Virtual Machine Stacks
概念定义
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.
In the First Edition of The Java® Virtual Machine Specification, the Java Virtual Machine stack was known as the Java stack.
This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen independently when that stack is created.
A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of Java Virtual Machine stacks, as well as, in the case of dynamically expanding or contracting Java Virtual Machine stacks, control over the maximum and minimum sizes.
The following exceptional conditions are associated with Java Virtual Machine stacks:
- If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a
StackOverflowError
.- If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an
OutOfMemoryError
.
直译:每个Java虚拟机线程都有一个与
线程同时创建的私有
Java虚拟机堆栈。Java虚拟机堆栈存储栈帧
(§2.6)。Java虚拟机堆栈类似于C等传统语言的堆栈:它保存局部变量和部分结果,并在方法调用和返回中发挥作用。因为Java虚拟机栈从来不会被直接操作,除了push和pop栈帧,栈帧可以被堆分配。Java虚拟机堆栈的内存不需要是连续的。在第一版的Java®虚拟机规范中,Java虚拟机栈被称为Java栈。
这个规范允许Java虚拟机栈具有固定的大小,或者根据计算的需要动态地扩展和收缩。如果Java虚拟机栈的大小是固定的,那么在创建每个Java虚拟机栈时可以独立选择该栈的大小。
Java虚拟机实现可以为程序员或用户提供对Java虚拟机栈初始大小的控制,以及在动态扩展或收缩Java虚拟机栈的情况下,对最大和最小大小的控制。
以下异常条件与Java虚拟机栈相关联:
如果线程中的计算需要比允许的更大的Java虚拟机堆栈,Java虚拟机会抛出StackOverflowError。
如果Java虚拟机栈可以动态地扩展,和扩张是未遂但可以可用内存不足影响扩张,或者内存不足可以创建一个新线程的初始Java虚拟机栈,Java虚拟机抛出一个OutOfMemoryError。
从官网的介绍中得出结论:java虚拟机栈是线程执行区域,用来保存线程执行调用状态。虚拟机堆栈是属于线程私有的,堆栈中存储着栈帧,每个方法对应着一个栈帧。栈帧存储着方法中的局部变量、操作数栈、动态链接、方法返回信息等。堆栈遵循FILO(first in last out)原则,在一个方法调用时,栈帧压栈,在方法调用完成后出栈。具体关于局部变量表、操作数栈的详细介绍可以看官网关于栈的描述。
内存模型结构
这里只画虚拟机栈以及其中局部变量表的内存模型图。
Heap
概念定义
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
The heap is created on virtual machine start-up. Heap storage for objects is reclaimed by an automatic storage management system (known as a garbage collector); objects are never explicitly deallocated. The Java Virtual Machine assumes no particular type of automatic storage management system, and the storage management technique may be chosen according to the implementor's system requirements. The heap may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger heap becomes unnecessary. The memory for the heap does not need to be contiguous.
A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the heap, as well as, if the heap can be dynamically expanded or contracted, control over the maximum and minimum heap size.
The following exceptional condition is associated with the heap:
- If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an
OutOfMemoryError
.
直译:Java虚拟机有一个堆,在所有Java虚拟机线程之间共享。堆是运行时数据区域,为所有类实例和数组分配内存。
堆在虚拟机启动时创建。对象的堆存储由自动存储管理系统(称为垃圾收集器)回收;对象永远不会显式地释放。Java虚拟机假设没有特定类型的自动存储管理系统,存储管理技术可以根据实现者的系统需求进行选择。堆的大小可以是固定的,也可以根据计算的需要进行扩展,如果不需要更大的堆,还可以收缩。堆的内存不需要是连续的。
Java虚拟机实现可以让程序员或用户控制堆的初始大小,如果堆可以动态扩展或收缩,还可以控制堆的最大和最小大小。
下面是与堆相关的异常情况:
如果计算需要的堆比自动存储管理系统提供的堆多,Java虚拟机会抛出OutOfMemoryError。
从官网定义得出,java虚拟机中只会存在一个堆,堆内存中数据线程共享,堆中存储所有类实例和数据。也是日常开发中,开发者需要重点关注的模块。因为对于虚拟机中的垃圾回收,主要是在堆中执行,关注并了解堆内存的内存模型以及相应垃圾回收算法会有效避免开发中可能出现的内存泄露、内存溢出等问题。堆内存采用分代策略划分内存区域,以提升垃圾回收效率。
内存模型结构
Method Area
概念定义
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.
The method area is created on virtual machine start-up. Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it. This specification does not mandate the location of the method area or the policies used to manage compiled code. The method area may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger method area becomes unnecessary. The memory for the method area does not need to be contiguous.
A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the method area, as well as, in the case of a varying-size method area, control over the maximum and minimum method area size.
The following exceptional condition is associated with the method area:
- If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an
OutOfMemoryError
.
直译:Java虚拟机有一个在所有Java虚拟机线程之间共享的方法区域。方法区域类似于传统语言编译代码的存储区域,或类似于操作系统进程中的“文本”段。它存储每个类的结构,比如运行时常量池、字段和方法数据,以及方法和构造函数的代码,包括在类和实例初始化以及接口初始化中使用的特殊方法(§2.9)。
方法区域是在虚拟机启动时创建的。虽然方法区域在逻辑上是堆的一部分,但简单实现可能选择不进行垃圾收集或压缩。此规范不强制规定用于管理已编译代码的方法区域或策略的位置。方法区域可以是固定大小,也可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以收缩。方法区域的内存不需要是连续的。
Java虚拟机实现可以为程序员或用户提供对方法区域初始大小的控制,以及在方法区域大小可变的情况下,对最大和最小方法区域大小的控制。
以下异常情况与方法区域相关:
如果方法区域中的内存无法满足分配请求,Java虚拟机将抛出OutOfMemoryError错误。
从官网定义得出,方法区为虚拟机存储类元数据信息、常量池、字段和方法数据等。方法区线程共享。
关于常量池的定义可以参考官网。
Native Method Stacks
概念定义
An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support
native
methods (methods written in a language other than the Java programming language). Native method stacks may also be used by the implementation of an interpreter for the Java Virtual Machine's instruction set in a language such as C. Java Virtual Machine implementations that cannot loadnative
methods and that do not themselves rely on conventional stacks need not supply native method stacks. If supplied, native method stacks are typically allocated per thread when each thread is created.This specification permits native method stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the native method stacks are of a fixed size, the size of each native method stack may be chosen independently when that stack is created.
A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the native method stacks, as well as, in the case of varying-size native method stacks, control over the maximum and minimum method stack sizes.
The following exceptional conditions are associated with native method stacks:
- If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a
StackOverflowError
.- If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an
OutOfMemoryError
.
直译:Java虚拟机的实现可以使用传统的栈(通俗地称为“C栈”)来支持
native
方法(用Java编程语言以外的语言编写的方法)。本地方法栈的实现也可以使用一个翻译为Java虚拟机的指令集的语言如c . Java虚拟机实现,无法加载本地方法,自己不依赖传统的本地方法栈栈不需要供应。如果提供了本机方法栈,则通常在创建每个线程时为每个线程分配本机方法栈。该规范允许本地方法堆栈具有固定的大小,或者根据计算的需要动态地展开和收缩。如果本机方法堆栈的大小是固定的,那么可以在创建该堆栈时独立选择每个本机方法堆栈的大小。
Java虚拟机实现可以为程序员或用户提供对原生方法栈初始大小的控制,并且,在原生方法栈大小可变的情况下,还可以控制最大和最小方法栈大小。
下面的异常条件与本机方法栈相关联:
如果线程中的计算需要比允许的更大的本机方法堆栈,Java虚拟机将抛出StackOverflowError。
如果可以动态扩展本机方法堆栈,并且尝试扩展本机方法堆栈,但是可用内存不足,或者如果可用内存不足,可以为新线程创建初始本机方法堆栈,Java虚拟机将抛出OutOfMemoryError。
从官网定义中得出,本地方法栈就是用来支持java调用native方法的传统栈空间。一般情况下,无需开发人员过多关注。