http://homepages.ius.edu/RWISMAN/C431/html/JVM.htm
Java Virtual Machine |
ONLINE RESOURCES
OVERVIEW
The Java Virtual Machine (JVM) is an abstract computing machine based on a stack-oriented architecture with method access to a single, current frame.
Operands are on the stack, for example: 27 - 4
Stack
TOS
21 34 15 bipush 27
bipush 4
Stack
TOS
21 34 15 27 4 isub
Stack
TOS
21 34 15 23 The following set of examples illustrate the organization of the JVM and the form code generation must produce in order to be compatible for execution. The approach will be to present Java source code and the corresponding assembly code for the JVM.
Two tools are very useful for our task of generating correct assembly code:
- jasmin - an assembler that produces a class file for the JVM
- jasper - which translates class file format byte-codes into an assembler file compatible with jasmin.
The JVM implements a pure stack-based architecture - generally there are no accessible registers, only access to the stack and the frame of the currently executing method.
It is important to recognize that stack and frame frame operations are independent; stack operations do not affect the frame except when moving data between the two.
- Stack is accessed by the usual push and pop operations which only operate at the top of stack (TOS).
- Frame is accessed by offsets from the start of the frame which allows random access.
Frame
this 0 1 2 3 4
21 34 15 -4 27 Stack
TOS
21 34 15 -4 27 Memory
19 20 21 22 23
45 98 105 62 111 Stack and frame operations include:
- bipush 100 - push byte 100 as integer to TOS.
- iconst_5 - essentially the same as bipush 5, only defined for integers -1..5.
- iload 1 - push the value from frame index 1 to TOS
- istore 2 - pop the value from TOS to frame index 2.
- aload 0 - 'this' object is at 0 of the current method frame and must be a reference. Push from frame index 0 to TOS.
- astore 0 - pop from TOS to frame index 0.
- dup - duplicates the TOS by pushing TOS.
Exercise - What is the result of each of the above on the Stack?
Exercise - What is the significance of this in object-oriented programming?
STACKS and FRAMES
A key insight is that the stack of the caller is the frame of thecallee (at least the parameter portion) when a method is called.
Consider the following example in Java and the corresponding JVM assembly:
Caller Callee new B().m(11, 12); class B {
void m(int a, int b) {}CallerStack
new B
bipush 11
bipush 12
invokevirtual B/m(II)V
reference to B object 11 12 Callee Frame
this
a 11
b 12
0 reference to B object 1 11 2 12 Another example illustrates the interaction between methods using the stack to return results. The callee always leaves a method result at the TOS for the caller.
Caller Callee int x;
x = new B().m(11, 12);class B {
int m(int a, int b) { return 13;}CallerStackbefore call
new B
bipush 11
bipush 12
invokevirtual B/m(II)I
reference to B object 11 12 Caller Stack after call
13 TOS Callee Frame Callee Stack
this
a 11
b 12
0 reference to B object 1 11 2 12
.method public m(II)I
bipush 13
ireturn
.end method
13
TOS
Exercise - What does the following mean?
- .method public m(II)I
- invokevirtual C/m(II)I
- bipush 13
- ireturn
Example - Accessing a parameter.
- Each class generates a separate class file when compiled.
- Java classes ex1 and ex2 were in one file, ex1.java, which was compiled then disassembled using jasper.
Frame and parameter passing: note that method stack operations do not affect frame references of that method.
- new ex2 - Line 16 of ex1 allocates new ex2 object and places reference on top of stack (TOS).
- dup - duplicates the ex2 object on TOS.
- invokespecial ex2/<init>()V - calls ex2 constructor, note that line 8
- bipush 100 - pushes integer 100 to TOS.
- invokevirtual ex2/f2(I)V - calls ex2 method f2,this is at frame offset 0, parameter n at offset 1, and local i at offset 2.
- iload_1 - copies frame offset 1 (i.e. n) to TOS
- istore_2 - copies TOS to local i at frame offset 2.
- public class ex1 {
- public static void main(String [] args) {
- new ex2().f2( 100 );
- }
- }
- class ex2 {
- public void f2( int n ) {
- int i;
- i = n;
- }
- }
Frame
0 this = ex2 1 n = 100 2 i
- .source ex1.java
- .class public ex1
- .super java/lang/Object
- .method public <init>()V
- .limit stack 1
- .limit locals 1
- .line 1
- aload_0 ; 'this'
- invokespecial java/lang/Object/<init>()V
- return
- .end method
- .method public static main([Ljava/lang/String;)V
- .limit stack 2
- .limit locals 1 ; STACK
- .line 3 ; ____________
- new ex2 ; | ex2 reference |
- dup ; | ex2 reference |
- invokespecial ex2/<init>()V ; ____________
- bipush 100 ; | ex2 reference |
- invokevirtual ex2/f2(I)V ;| 100 |
.line 4- return
- .end method
- .source ex1.java
- .class ex2
- .super java/lang/Object
- .method <init>()V
- .limit stack 1
- .limit locals 1
- .line 7
- aload_0
- invokespecial java/lang/Object/<init>()V
- return
- .end method
- .method public f2(I)V
- .limit stack 1
- .limit locals 3
- .line 9
- iload_1 ; n -> TOS
- istore_2 ; TOS -> i
- .line 10
- return
- .end method
Exercise - What does the following mean?
- dup
- .limit stack 2
- istore 2
- iload 1
Exercise - Explain in .method public f2(I)V
- .limit stack 1
- .limit locals 3
Instance variables - instance variables (fields) are not part of the frame or stack but are accessed by this and field name.
Example - Returning a result and instance variables (fields).
- The field j is defined in line 29.
j = m;
is equivalent to lines 45-47:
- aload_0 ; this
- iload_2 ; m
- putfield ex2/j I ; j = m
Recall that this is at frame offset 0, and m at offset 2.
- return j;
is equivalent to lines 56-58:
- aload_0
- getfield ex2/j I
- ireturn
Where the return value is at TOS.
- public class ex1 {
- public static void main(String [] args) {
- new ex2().f2( 100, 200 );
- }
- }
- class ex2 {
- int j;
- public int f2( int n, int m ) {
- int i = n;
- j = m;
- j = j + i;
- return j;
- }
- }
Frame
0 this 1 n 2 m 3 i
- .source ex1.java
- .class public ex1
- .super java/lang/Object
- .method public <init>()V
- .limit stack 1
- .limit locals 1
- .line 1
- aload_0
- invokespecial java/lang/Object/<init>()V
- return
- .end method
- .method public static main([Ljava/lang/String;)V
- .limit stack 3
- .limit locals 1
- .line 3
- new ex2
- dup
- invokespecial ex2/<init>()V
- bipush 100
- sipush 200
- invokevirtual ex2/f2(II)I
- pop
- .line 4
- return
- .end method
- .source ex1.java
- .class ex2
- .super java/lang/Object
- .field j I
- .method public <init>()V
- .limit stack 1
- .limit locals 1
- .line 10
- aload_0
- invokespecial java/lang/Object/<init>()V
- return
- .end method
- .method public f2(II)I
- .limit stack 3
- .limit locals 4
- .line 13
- iload_1
- istore_3
- .line 14
- aload_0
- iload_2
- putfield ex2/j I
- .line 15
- aload_0
- aload_0
- getfield ex2/j I
- iload_3
- iadd
- putfield ex2/j I
- .line 16
- aload_0
- getfield ex2/j I
- ireturn
- .end method
Exercise
- Explain lines 49-54. Specifically, where and what are the operands of line 53? Draw the stack to illustrate your answer.
- What is the effect of line 54?
- Explain lines 56-57.
- Why is local limit 4?
- Why is the stack limit 3?
FRAMES IN THE MiniJava COMPILER
The text presents a model for frames closely connected with later subjects of optimization and code production for an intermediate language.
We will first consider frame, class and method generation for the JVM architecture only; allowing us to examine many of the remaining steps in compilation in a simpler context before tackling the more general approach of the text.
Recall the SymbolTable package implementation which holds declaration information such as the name and type of variables.
Frames are only associated with methods and constructors, since MiniJava has only the default constructor, we are concerned only with frames for methods. The following classifies each declaration part of a MiniJava program as it relates to frames.
Class - Class data (i.e. name, parent, methods, globals) is recorded in the SymbolTable but is not part of the frame.
Class generation is straightforward consisting of:
- Lines 26-28
- optional source file name
- required class name
- parent class
- Line 29
- field names and type
- Line 30
- ex2 class constructor with 0 parameters.
- Line 31
- stack limit of 1 for one parameter in call to parent constructor at Line 34-35.
- Line 32
- number of parameters + locals + this - the frame size.
- .source ex1.java
- .class ex2
- .super java/lang/Object
- .field j I
- .method public <init>()V
- .limit stack 1
- .limit locals 1
- .line 10
- aload_0
- invokespecial java/lang/Object/<init>()V
- return
- .end method
class ex2 { int j;
Globals
Globals name (fields) and type are recorded in the SymbolTable but are not part of the frame. The example above illustrates how globals must be defined as part of the class.
Methods
- public int f2( int n, int m ) {
- int i = n;
- j = m;
- j = j + i;
- return j;
- }
- }
- .method public f2(II)I
- .limit stack 3
- .limit locals 4
- .line 13
- iload_1
- istore_3
- .line 14
- aload_0
- iload_2
- putfield ex2/j I
- .line 15
- aload_0
- aload_0
- getfield ex2/j I
- iload_3
- iadd
- putfield ex2/j I
- .line 16
- aload_0
- getfield ex2/j I
- ireturn
- .end method
Frame
0 this 1 n 2 m 3 i
A frame must be determined for each method, the essential data for compiling a method is:
- method name
- method type - for the return, MiniJava has void (return) or int (ireturn).
- parameters - this is first, the order in the parameter determines frame location of others.
- variables - assigned to a unique frame location following parameters.
- .limit stack - maximum stack space required due to pushes, parameters, etc.; often the maximum number of parameters passed to any callee. It is safer to specify more than needed, specifying to little results in a runtime exception.
- .limit locals - this + number of parameters + variables. As with the stack limit, it is allowed to set the limit above that needed, setting too low results in a runtime exception.
this
this is allocated first in the frame at location 0. Before an instance method call such as at Line 28, requires placing this at location 0 of the callee frame. The following constructs the frame for the putfield method that appears as:
- aload_0
- bipush 12
- putfield ex2/j I
Frame
0 this 1 12 Parameters/Variables
Parameters are allocated in the frame immediately after this. Variables immediately follow parameters.
Caller - constructs the frame by placing the object passed to this followed by parameters on the stack; then invoke the method. Notice that values are represented as bytes, etc. and extended when copied to the frame where possible:
bipush 100 has the following description:
- The immediate byte is sign-extended to an
int
value. That value is pushed onto the operand stack.sipush 200
The immediate unsigned byte1 and byte2 values are assembled into an intermediateshort
where the value of the short is ( byte1 << 8) | byte2. The intermediate value is then sign-extended to anint
value. That value is pushed onto the operand stack.
new ex2().f2( 100, 200 );
- new ex2
- bipush 100
- sipush 200
- invokevirtual ex2/f2(II)I
Callee - defines the frame size by limit described above. Parameters and variable values are accessed from the frame.
- frame - object references can be loaded from the frame to the TOS by the aload operation, integers by the iload. Stored from the TOS to the frame by the istore operation, etc.
- stack - the stack is not required to be balanced at the method return, the return address seems to be part of the JVM architecture.
- return - typed method returns (e.g. an int method) return the TOS.
- public int f2( int n, int m ) {
- int i = n;
- j = m;
- return i + j;
- .method public f2(II)I
- .limit stack 3
- .limit locals 4
- .line 13
- iload_1
- istore_3
- .line 14
- aload_0
- iload_2
- putfield ex2/j I
- .line 15
- aload_0
- getfield ex2/j I
- iload_3 ; i
- iadd ; TOS = i + j
- ireturn ; returns TOS
- JVM Specifications - Download site
- jasper - Download site
jasper is a disassembler of Java class files to an assembly program. Basically the steps are:
- Compile the Java program file.
- Disassemble a class file to assembly, using example.class
- Home: java -jar \jasper\jasper.jar example.class
- IUS: java -jar v:\common\user\C431\jasper.jar example.class
- jasmin - Download site
jasmin assembles a JVM assembly file into a class file that can be executed by the JVM.
- Compile the Java program file to assembly language.
- Assemble a class file to assembly, using example.j
- Home: java -jar \jasmin\jasmin.jar example.j
java -cp . example.class
- IUS: java -jar v:\common\user\C431\jasmin.jar example.j
java -cp . example.class