Java虚拟机结构--堆栈

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.

译:Java虚拟机定义了许多运行时数据区被用于程序的执行,有一些数据区在虚拟机启动的时候创建,在虚拟机退出时销毁,另外一些数据区是针对每个线程的,即这些数据区是和线程的生命周期相同。

2.5.1. The pc Register
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.

译:
PC寄存器
Java虚拟机可以支持并发线程的执行。每一个Java线程拥有自己的pc寄存器,从任何地方来看,每一个java线程执行单个方法的代码,这个方法叫做当前方法(current method)。如果这不是个本地方法,那么pc寄存器包含的是当前执行代码的虚拟机指令地址,如果当前方法是本地方法,那么pc寄存器的值是undefined。虚拟机的pc寄存器是足够长可以用于容纳返回地址和本地方法指针的。

2.5.2. 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.

译:每一个线程在创建的时候,都会同时创建一个私有的栈用来存储栈帧.这个栈和传统语言(比如C语言)的栈类似,用来保存局部变量和计算结果,并用来实现方法调用和返回。因为栈只有添加栈帧和删除栈帧的操作,这个栈帧可能是在堆上分配的。此外,栈在内存上不需要是连续的。

规范允许栈的大小可以是固定的,也可以根据需要来动态增大或减小,如果栈的大小是固定的,那么每一个栈的大小是可以是独立的。有些虚拟机的实现中,实现者会给开发人员提供一个栈的初始化大小,以及动态增加的最大容量。

栈有两种异常:
如果线程的计算需要申请的栈大小超过了虚拟机的允许值,那么虚拟机会抛出一个StackOverflowError.
如果虚拟机的栈是动态调整的,那么扩展所需要的栈大小超过了当前可用内存,或者没有足够的内存来创建一个新线程,这时虚拟机会抛出一个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.

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堆是所有线程共享的,并且在运行时,对象和数组实例都是在堆上分配的。
堆和虚拟机的生命周期相同,堆中的对象是被自动回收系统来回收的(也就是GC),对象不能被显式的回收,虚拟机假设GC没有特定的类别,并且回收技术根据实现者的系统要求。堆的大小可以是固定大小,或者是动态的增加或删除。
实现者可能会给开发人员提供参数用来控制堆的初始大小,同时,如果堆的大小是动态调整的,那么也会提供参数来控制堆的最大容量和最小容量。
如果计算所需要的堆大小超过了内存管理系统所能够提供的大小,那么会抛出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.

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.

译:
方法区
虚拟机有一块所有线程共享的方法区, 这个区的结构和传统语言的编译代码结构相同,和操作系统进程的文本段也类似.它用来存储每个对象的结构,比如运行时常量池,字段,方法数据,方法代码,以及构造函数.

方法区的生命周期和虚拟机进程相同,尽管方法区在逻辑上属于堆的一部分,但是在一般的实现中,GC不能管理此部分内容。规范并不要强制规定方法区的内存位置以及管理代码的策略。方法区可以是固定大小或者动态增加,且在内存上可以不连续。

一般的虚拟机实现者会提供参数来控制方法区的初始容量以及最大/最小容量。

如果方法区的大小不能满足分配需求,则会抛出异常:OutOfMemoryError

解读:这里说的方法区,其实就是我们使用JDK的PermGen区域。

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.

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.

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.

See §5 (Loading, Linking, and Initializing) for information about the construction of the run-time constant pool.

译:
常量池
运行时常量池是通过每一个对象,接口的class文件结构中的常量池表来表示。常量池包含了许多的常量,它的范围就是在编译期确定的数值长度,以及在运行期所确定的字段引用。常量池所提供的功能和传统语言的符号表类似。
运行时常量池是在方法区上分配的,每一个对象的常量池是在对象创建时分配的。

当创建一个对象或接口所需要的常量池大小超过虚拟机的方法区大小,那么会抛出异常:OutOfMemoryError

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.

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以外的语言所写的方法),本地方法栈可能要实现虚拟机指令的翻译。
本地方法栈的大小可以是固定的或者是动态调整,一般实现者会提供参数给程序员来控制栈的大小或者最大最小容量。

如果一个线程所需要的栈大小超过了虚拟机规定的大小,那么虚拟机会抛出StackOverflowError。
如果没有足够的内存来进行动态分配栈大小,那么会抛出一个OutOfMemoryError.

2.6. Frames
A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java Virtual Machine stack (§2.5.2) of the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to the run-time constant pool (§2.5.5) of the class of the current method.

A frame may be extended with additional implementation-specific information, such as debugging information.

The sizes of the local variable array and the operand stack are determined at compile-time and are supplied along with the code for the method associated with the frame (§4.7.3). Thus the size of the frame data structure depends only on the implementation of the Java Virtual Machine, and the memory for these structures can be allocated simultaneously on method invocation.

Only one frame, the frame for the executing method, is active at any point in a given thread of control. This frame is referred to as the current frame, and its method is known as the current method. The class in which the current method is defined is the current class. Operations on local variables and the operand stack are typically with reference to the current frame.

A frame ceases to be current if its method invokes another method or if its method completes. When a method is invoked, a new frame is created and becomes current when control transfers to the new method. On method return, the current frame passes back the result of its method invocation, if any, to the previous frame. The current frame is then discarded as the previous frame becomes the current one.

Note that a frame created by a thread is local to that thread and cannot be referenced by any other thread.

译:
栈帧
栈帧用来保存数据和部分计算结果,以及实现动态连接,方法返回值,还有异常的传递。
当一个方法被调用的时候,会创建一个新的栈帧,调用完成后,对应的栈帧会销毁,且不论是正常还是异常的完成。栈帧是在栈上被分配的。每一个栈帧有自己的变量数组,操作栈,以及当前方法所在对象所指向常量池的引用。
一个栈帧有可能被其他具体实现细节上的内容扩展,比如调试信息。
变量数组和操作栈的大小要求在编译期间确定,此外,栈帧中数据结构的容量也仅仅依赖具体的虚拟机实现细节。这一部分内存能够被同时分配使用。
在任何时候,只有一个栈帧用于执行方法,这个栈帧叫做当前栈帧,这个方法叫做当前方法,这个方法所在的对象叫做当前对象。在变量数组和操作栈上面的操作,将会被指向当前栈帧。
当一个方法调用另外一个方法,或者一个这个方法执行完成的时候,那么栈帧就不再是当前的栈帧了。当一个方法被调用,一个新的栈帧会被创建并且当控制流程转向新的栈帧时,这个栈帧会转换为当前栈帧。当方法返回,那么当前栈帧传回结果给调用者的栈帧,因此不论如何,一个方法执行完毕,那么控制转向到上一个栈帧,当前栈帧会被丢弃,上一个栈帧会变成当前栈帧。
此外,栈是线程私有的,栈帧也是。

2.6.1. Local Variables
Each frame (§2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (§4.7.3).

A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.

Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array.

A value of type long or type double occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.

The Java Virtual Machine does not require n to be even. In intuitive terms, values of types long and double need not be 64-bit aligned in the local variables array. Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.

The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this in the Java programming language). Any parameters are subsequently passed in consecutive local variables starting from local variable 1.

译:
每一个栈帧包含一个变量数组,这就是熟知的本地变量,且数组长度是在编译期间确定的。当前方法的代码和栈帧关联的时候,这些本地变量会使用二进制码来表示。
一个本地变量可以用来保存除了long,double类型的变量,long double类型的变量会使用两个本地变量来保存。
本地变量通过索引来寻址,第一个本地变量的索引为0,一个正整数类型被认为是进入变量数组的索引。
long,double类型需要占用两个连续的本地变量,这种类型的值会使用较小的那个索引来寻址.
虚拟机使用本地变量来给方法调用传递参数,方法调用时,变量数组中所有的变量都会被从传递,也就是从索引0开始的。当实例方法被调用时,索引0被用来传递this引用。

2.6.2. Operand Stacks
Each frame (§2.6) contains a last-in-first-out (LIFO) stack known as its operand stack. The maximum depth of the operand stack of a frame is determined at compile-time and is supplied along with the code for the method associated with the frame (§4.7.3).

Where it is clear by context, we will sometimes refer to the operand stack of the current frame as simply the operand stack.

The operand stack is empty when the frame that contains it is created. The Java Virtual Machine supplies instructions to load constants or values from local variables or fields onto the operand stack. Other Java Virtual Machine instructions take operands from the operand stack, operate on them, and push the result back onto the operand stack. The operand stack is also used to prepare parameters to be passed to methods and to receive method results.

For example, the iadd instruction (§iadd) adds two int values together. It requires that the int values to be added be the top two values of the operand stack, pushed there by previous instructions. Both of the int values are popped from the operand stack. They are added, and their sum is pushed back onto the operand stack. Subcomputations may be nested on the operand stack, resulting in values that can be used by the encompassing computation.

Each entry on the operand stack can hold a value of any Java Virtual Machine type, including a value of type long or type double.

Values from the operand stack must be operated upon in ways appropriate to their types. It is not possible, for example, to push two int values and subsequently treat them as a long or to push two float values and subsequently add them with an iadd instruction. A small number of Java Virtual Machine instructions (the dup instructions (§dup) and swap (§swap)) operate on run-time data areas as raw values without regard to their specific types; these instructions are defined in such a way that they cannot be used to modify or break up individual values. These restrictions on operand stack manipulation are enforced through class file verification (§4.10).

At any point in time, an operand stack has an associated depth, where a value of type long or double contributes two units to the depth and a value of any other type contributes one unit.

译:
操作栈

每个栈帧包含一个后进先出的队列,这个队列叫做操作栈,每个栈帧的操作栈最大深度在编译期间确定。
当栈帧被创建时,操作栈是空的,虚拟机提供指令来加载常量或变量到操作栈上来,其他一些虚拟机指令在操作栈上进行操作数据,并且将结果返回到操作栈上。操作栈同样用来传递参数给方法调用,或者接收其他方法返回值。

比如:iadd指令用于两个整型数据的加法操作,指令要求这两个整型数据被添加到操作栈的顶部。这条指令将两个操作数从栈中取出后相加,并将结果压入栈。
操作栈的每一个条目都可以用来保存java虚拟机支持的数据类型。

操作栈中的数据必须依据他们的类型来进行操作。举一个违反规定的操作:将int类型的数据当作long类型来处理,或者是将两个float类型的数据使用iadd指令来操作。

有一部分虚拟机指令会将运行时数据当作原始类型来处理,不论他们是何种特殊类型。这些指令通过特殊的方式来定义,且不能用来修改这些变量值。

2.6.3. Dynamic Linking
Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code. The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references. Dynamic linking translates these symbolic method references into concrete method references, loading classes as necessary to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the run-time location of these variables.
This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.

译:每一个栈帧包含一个指向运行时常量池的引用,这个常量池包含当前方法的类型用来支持到方法代码的动态链接,class文件的方法代码指向一个被调用的方法并且变量通过符号引用来访问。动态链接用来转换这些方法符号到具体的方法上。

这一小节就翻译完了,从早上9点多写到下午4点,内容比较复杂,昨天还专门看了一遍这些内容。不过感觉虽然学的java虚拟机,但是其他语言的原理其实也是类似。水平真的有限啊….有好多地方翻译的不好,虽然英文能明白。各位看官不要笑话,希望可以帮忙纠正。谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值