JVM学习笔记-局部变量区(Local Variables)
The local variables section of the Java stack frame is organized as a zero-based array of words. Instructions that use a value from the local variables section provide an index into the zero-based array. Values of type int, float, reference, and returnValue occupy one entry in the local variables array. Values of type byte, short, and char are converted to int before being stored into the local variables. Values of type long and double occupy two consecutive entries in the array.
Java栈帧的局部变量区被组织为一个以字长为单位,从0开始计数的数组。字节码指令通过从0开始的索引来使用其中的数据。类型为int、float、reference和returnAddress的值在数组中只占据一项,而类型为byte、short和char的值在存入数组前都被转换为int值,因而同样占据一项。但是类型为long和double的值在数组中却占连续的两项。
To refer to a long or double in the local variables, instructions provide the index of the first of the two consecutive entries occupied by the value. For example, if a long occupies array entries three and four, instructions would refer to that long by index three. All values in the local variables are word-aligned. Dual-entry longs and doubles can start at any index.
在访问局部变量中的long和double值的时候,指令只需指出连续两项中第一项的索引值。例如某个long值占据第三四项,那么指令会取索引为3的long值。局部变量区的所有值都是字对齐的,long和double这样占据两项数组元素的值同样可以起始于任何索引。
The local variables section contains a method's parameters and local variables. Compilers place the parameters into the local variable array first, in the order in which they are declared. Figure 5-9 shows the local variables section for the following two methods:
局部变量区包含对应方法的参数和局部变量。编译器首先按声明的顺序把这些参数放入局部变量数组。
图5-9描绘了下面两个方法的局部变量区。
begin
// On CD-ROM in file jvm/ex3/Example3a.java
class Example3a {
public static int runClassMethod(int i, long l, float f,
double d, Object o, byte b) {
return 0;
}
public int runInstanceMethod(char c, double d, short s,
boolean b) {
return 0;
}
}
end
Figure 5-9
Note that Figure 5-9 shows that the first parameter in the local variables for runInstanceMethod() is of type reference, even though no such parameter appears in the source code. This is the hidden this reference passed to every instance method. Instance methods use this reference to access the instance data of the object upon which they were invoked. As you can see by looking at the local variables for runClassMethod() in Figure 5-9, class methods do not receive a hidden this. Class methods are not invoked on objects. You can't directly access a class's instance variables from a class method, because there is no instance associated with the method invocation.
注意,在图5-9中显示的方法runInstanceMethod()中,局部变量中第一个参数是一个reference(引用)类型,尽管在方法源代码中没有显式声明这个参数,但这个参数this对于任何一个实例方法都是隐含加入的,它用来表示调用该方法的对象本身,与此相反,方法runClassMethod()中就没有这个隐含的this变量,因为它是一个类方法。类方法只与类相关,而与具体的对象无关,不能直接通过类方法访问类实例的变量,因为在方法调用的时候没有关联到一个具体实例。
Note also that types byte, short, char, and boolean in the source code become ints in the local variables. This is also true of the operand stack. As mentioned earlier, the boolean type is not supported directly by the Java Virtual Machine. The Java compiler always uses ints to represent boolean values in the local variables or operand stack. Data types byte, short, and char, however, are supported directly by the Java Virtual Machine. These can be stored on the heap as instance variables or array elements, or in the method area as class variables. When placed into local variables or the operand stack, however, values of type byte, short, and char are converted into ints. They are manipulated as ints while on the stack frame, then converted back into byte, short, or char when stored back into heap or method area.
我们注意到,在源代码中的byte,short,char,和boolean在局部变量区都被转换成了int,在操作数栈中也一样,前面我们曾经说过,虚拟机并不直接支持boolean类型,因此Java编译器总是用int来表示boolean,但Java虚拟机对byte,short和char是直接支持的,这些类型的值可以作为实例变量或者数组元素存储在局部变量区,也可以作为类变量存储在方法区中,但在局部变量区和操作数栈中都会被转换成int类型的值,它们在栈帧中的时候都是当作int来进行处理的,只有当它被存回堆或方法区时,才会转换回原来的类型。
Also note that Object o is passed as a reference to runClassMethod(). In Java, all objects are passed by reference. As all objects are stored on the heap, you will never find an image of an object in the local variables or operand stack, only object references.
同样需要注意的是作为runClassMethod()的引用被传递的参数Objecto.在Java中,所有的变量都按引用传递,并且都存储在堆中,永远都不会在局部变量区或操作数栈中发现对象的拷贝,只会有对象引用。
Aside from a methodís parameters, which compilers must place into the local variables array first and in order of declaration, Java compilers can arrange the local variables array as they wish. Compilers can place the methodís local variables into the array in any order, and they can use the same array entry for more than one local variable. For example, if two local variables have limited scopes that donít overlap, such as the i and j local variables in Example3b below, compilers are free to use the same array entry for both variables. During the first half of the method, before j comes into scope, entry zero could be used for i. During the second half of the method, after i has gone out of scope, entry zero could be used for j.
除了Java方法的参数(编译器首先严格按照它们的声明顺序放到局部变量数组中,而对于真正的局部变量,它可以任意决定放置顺序,甚至可以用一个索引指代两个局部变量)— 比如当两个局部变量的作用域不重叠时,像下面Example3b中的局部变量i和j就是这种情况:在方法的前半段,在j开始生效前,0号索引的入口可以被用来代表i在方法的后半段,i已经超过了有效作用域,0号入口就可以用来表示j了。
begin
// On CD-ROM in file jvm/ex3/Example3b.java
class Example3b {
public static void runtwoLoops() {
for (int i = 0; i < 10; ++i) {
System.out.println(i);
}
for (int j = 9; j = 0; --j) {
System.out.println(j);
}
}
}
end
As with all the other runtime memory areas, implementation designers can use whatever data structures they deem most appropriate to represent the local variables. The Java Virtual Machine specification does not indicate how longs and doubles should be split across the two array entries they occupy. Implementations that use a word size of 64 bits could, for example, store the entire long or double in the lower of the two consecutive entries, leaving the higher entry unused.
和其他运行时内存区一样,虚拟机的实现者可以为局部变量区设计任意的数据结构。比如对于怎样把long和double类型的值存储到两个数组项中,Java虚拟机规范没有指定。假如某个虚拟机实现的字长为64位,这时就可以把整个long或double数据放在数组中相邻两数组项的低项内,而使高项保持为空。