前言
本文主要介绍JVM的运行时数据区
来自Oracle文档 Java Virtual Machine Specification -- Chapter 2. The Structure of the Java Virtual Machine 2.5
Link : http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5
2.5. 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.
JVM定义了我们执行程序时的运行时数据区. 其中一些数据区是在JVM启动的时候创建并在JVM退出的时候才会销毁的. 还有一些数据区是每个线程都有的. 每个线程都有的数据区(per-thread data areas)在每个线程创建的时候创建并在线程结束的时候销毁.
2.5.1. The pc
Register
pc 寄存器
The 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 not native
, the pc
register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native
, the value of the Java Virtual Machine's pc
register is undefined. The Java Virtual Machine's pc
register is wide enough to hold a returnAddress
or a native pointer on the specific platform.
JVM可以一次支持多个线程执行.每个JVM线程都有他自己的pc(program counter, 程序计数)寄存器. 在任何时间点, JVM线程都在执行一个方法的代码, 也就是这个线程的当前方法. 如果这个方法不是native的, 那么pc寄存器包含当前正在执行的方法的地址. 假如当前正在执行的方法是native的, 那么pc寄存器的值将是undefined. pc寄存器的大小足以保存一个returnAddress 或者一个特定平台上的native指针.
2.5.2. Java Virtual Machine Stacks
JVM 栈
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.
每个JVM线程都有一个私有的JVM stack, 这个stack和thread同时创建. 一个JVM stack用来存储frame.JVM stack类似于通语言(例如 C)的stack: 他保存局部变量和结果, 并且参与到方法调用和返回中.因为JVM stack除了push和pop frame之外从来不会被直接操作,frame可能被非配到heap中. JVM stack的内存空间可以不连续.
In The Java Virtual Machine Specification, First Edition, the Java Virtual Machine stack was known as the Java stack.
在 "The Java Virtual Machine Specification, First Edition" 中, JVM stack 被认为是 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.
这个规范允许JVM stack固定大小或根据估算动态扩容或收缩. 加入JVM stack是固定大小的,那么每个JVM stack的size可能是在stack创建的时候自主选择的.
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.
JVM的实现可能会提供程序或用户支配statck初始化大小的能力, 同样的, 控制动态扩容或收缩的最大值和最小值
The following exceptional conditions are associated with Java Virtual Machine stacks:
以下是JVM stack相关的例外情况
If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a
*Error
.- 假如线程的操作需要超过允许的statck内存大小, JVM将会抛出*Error.
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
.- 如果JVM stack可以动态扩容, 那么会进行扩容尝试, 但是如果内存不足则会影响这次扩容, 或者在内存不足的情况下为一个新的线程创建一个JVM stack, JVM将会抛出 OutOfMemoryError
2.5.3. 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.
JVM拥有一个由所有JVM线程共享的heap.heap是一个用来存储所有class实例和数组的运行时数据区.
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.
heap在vm启动时创建. heap的对象存储会被一个自动存储管理系统回收(称作garbege collector); objects从不会被显式解除分配空间.JVM假定自动存储管理系统没有特例, 并且存储管理技术可能会根据实现类的系统需要来选择.heap可能是固定大小的,也有可能是根据操作需要扩容的.并且当大的heap没必要时会收缩变小. heap的内存空间不需要是连续的.
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.
JVM的实现可能会提供该用户控制heap的初始化大小的功能,同样,加入heap是动态扩容或收缩的,也可以控制最大和最小heap size
The following exceptional condition is associated with the heap:
下面是和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
.- 假如操作需要超过自动存储管理系统定义的heap大小,JVM将会抛出OutOfMemoryError
2.5.4. 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.
JVM有一个在所有线程之间共享的方法区.方法区和普通语言的编译代码的存储区或者操作系统进程中的"text" segment类似.他存储每个类结构: 例如运行时常量池, 变量和方法数据, 以及方法和构造器的代码, 包括一些class和instance以及interface的初始化方法.
方法区存放了类的信息,所以方法区应该也是位于持久代
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 version of the Java Virtual Machine 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.
一个方法区随着VM的启动被创建.即使方法区逻辑上讲是heap的一部分, 简单的实现可能不会对他进行垃圾回收和碎片整理. 这个版本的JVM规范没有强制规定方法区的位置或政策来管理编译的代码.方法区可以是固定大小的也可以是动态扩容收缩的.它的内存不需要连续
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.
JVM实现提供用户控制方法区初始化大小的功能, 同样, 可以控制方法区动态扩容收缩的最大值和最小值
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
.- 假如方法区的内存不能满足方法区分配需求, JVM将会抛出OutOfMemoryError.
2.5.5. Run-Time Constant Pool
运行时常量池
A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool
table in a class
file (§4.4). It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time. The run-time constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.
运行时常量池是class文件中constant_pool的per-class, per-interface的运行时表示.它包括好几种常量,包括编译时方法就知道的数值文字和运行时必须确定的成员引用. 运行时常量池提供了类似于普通语言的符号表功能, 虽然他包含比符号表更广的数据范围.
Each run-time constant pool is allocated from the Java Virtual Machine's method area (§2.5.4). The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.
每个运行时常量池都是从JVM的方法区分配的.class或interface的运行时常量池在class和interface被JVM创建时创建.
The following exceptional condition is associated with the construction of the run-time constant pool for a class or interface:
下面是运行时常量池的意外情况
When creating a class or interface, if the construction of the run-time constant pool requires more memory than can be made available in the method area of the Java Virtual Machine, the Java Virtual Machine throws an
OutOfMemoryError
.- 当创建一个class和interface时候,如果运行时常量池需要的内存超过方法区内存, 则JVM抛出OutOfMemoryError
See §5 for information about the construction of the run-time constant pool.
译者按: 运行时常量池应该位于持久代(PermGen), 因为如下代码可以很快抛出 java.lang.OutOfMemoryError: PermGen space
List<String> array = new ArrayList<String>();
int i = 0;
while (true) {
String s = String.valueOf(++i);
for (int j = 0; j < i; j++) s += s;
array.add(s.intern());
}
2.5.6. 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 load native
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.
JVM使用常规stack, 口语叫 "c stack", 来支持native方法(用非java语言编写的方法). native method statck 也会被JVM设置在别的语言里的解释器使用(例如C). 无法加载native方法,且本身也不会依赖常规栈的JVM实现不需要提供本地方法栈.如果提供了,本地方法栈通常在每个线程被创建时创建.
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.
这个技术规范允许本地方发展是固定改大小的或动态扩容收缩的.如果是固定大小,这个大小可能在stack创建时指定.
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.
JVM提供了用户控制本地方法栈的初始大小的功能, 同样, 可以控制动态变化大小时内存的最大值和最小值.
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
*Error
.- 假如线程里的操作需要一个超过stack规定大小的内存,JVM抛出*Error
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
.- 如果本地方法栈可以动态扩容并且试图在内存不足时扩容,或者内存不足时为新线程初始化新的本地方法栈,将抛出OutOfMemoryError.
-----------------------------------------------------------------------------------------------------------------------------------------------
翻译结束,下面是我自己的总结
The pc Register pc寄存器 |
Stack 栈 |
Native Method Statck 本地方法栈 |
Heap 堆 |
Method Area 方法区 |
Run-Time Constant Pool 运行时常量池 |
|
作用 |
线程正在运行的当前方法value 如果是非native方法,则value为方法地址 如果是native方法,则value为undefined |
保存frame: 局部变量和结果 | 支持本地方法(非Java语言方法) |
存储运行时class实例和数组分配的空间 垃圾回收(GC)机制作用的区域就是Heap 包含方法区, 运行时常量池 |
存储静态变量,方法和构造器代码, 类信息, 字符常量(位于运行时常量池) | 存储常量,如字符串 |
创建时机 | JVM线程创建时,每个线程一个 | JVM线程创建时,每个线程一个 | JVM线程创建时,每个线程一个 | JVM启动时,多线程共享 | JVM启动时, 多线程共享 | 从方法区分配,每个类和接口一个 |
固定分配空间 | NaN | true | true | true | true | true |
扩容/收缩空间 | NaN | true | true | true | true | true |
异常状况 | NaN |
线程操作内存需求超过当前stack大小,抛出*Error 动态扩容时内存不足,抛出OutOfMemoryError |
同 Stack | 线程操作内存需求超过Heap内存大小事,抛出OutOfMemoryError | 方法区内存不能满足分配需求时抛出OutOfMemoryError | 当创建一个类和接口时如果运行时常量池需要的内存超出方法区剩余内存,抛出OutOfMemoryError |