Download Introduction to Java Virtual Machine - Paper | CS 322 and more Papers Computer Science in PDF only on Docsity!
Java Virtual Machine
Jingke Li
Portland State University
Jingke Li (Portland State University) CS322 Java Virtual Machine 1 / 25
Java Virtual Machine
JVM is an abstract computer that executes Java bytecode.
Input Interface: .class files
Internal Architecture:
- Class loader — locating and loading .class files
- Bytecode verifier — verifying the integrity of the bytecodes
- Execution engine (interpreter or JIT compiler) — executing the bytecodes
Memory Model:
- Method area — for storing program code
- Heap — for storing class objects
- Java stacks — one stack per thread, for code execution
- PC registers — one per thread
- Native method stacks
The Class File
Each class file contains the definition of a single class or interface. It contains everything a JVM needs to know about the class or infterface. What exactly is in a .class file?
Consider Hello.java:
class Hello { public static void main(String[] a) { System.out.println("Hello World!"); } }
java -jar clsd Hello.class > Hello.dump
Jingke Li (Portland State University) CS322 Java Virtual Machine 3 / 25
Hello.dump
magic cafebabe versionpool size 49.0 29 1 tag(10) method ref 6/ 2 tag(9) field ref 16/173 tag(8) constant string 18 4 tag(10) method ref 19/ 5 tag(7) constant classs 216 tag(7) constant classs 22 7 tag(1) utf8 ’’ 8 tag(1) utf8 ’()V’9 tag(1) utf8 ’Code’ 10 tag(1) utf8 ’LineNumberTable’ 11 tag(1) utf8 ’main’12 tag(1) utf8 ’([Ljava/lang/String;)V’ 13 tag(1) utf8 ’SourceFile’ 14 tag(1) utf8 ’Hello.java’15 tag(12) name and type 7/ 16 tag(7) constant classs 23 17 tag(12) name and type 24/2518 tag(1) utf8 ’Hello World!’ 19 tag(7) constant classs 2620 tag(12) name and type 27/ 21 tag(1) utf8 ’Hello’ 22 tag(1) utf8 ’java/lang/Object’23 tag(1) utf8 ’java/lang/System’ 24 tag(1) utf8 ’out’ 25 tag(1) utf8 ’Ljava/io/PrintStream;’26 tag(1) utf8 ’java/io/PrintStream’ 27 tag(1) utf8 ’println’ 28 tag(1) utf8 ’(Ljava/lang/String;)V’
this_classsuper_class 20 21(#5)22(#6) interface count 0 field countmethod count (^02) method def 0 (#7) ()V(#8) attribute count0: attribute 1 Code(#9) 0: max_stack 1 0: max_locals0: code_length (^15) 2A B7 00 01 B 0: exception_table_length0: attribute count 01 0: 0: attribute LineNumberTable(#10) 0:0: 0: line number table length 10: line number table 1: 0/ method def 9 main(#11) ([Ljava/lang/String;)V(# attribute count0: attribute 1 Code(#9) 0: max_stack0: max_locals (^21) 0: code_length 9 0: exception_table_length B2 00 02 12 03 B6 00 04 B1 0 0: attribute count 1 0:0: 0: attribute0: line number table length 2 LineNumberTable(#10) 0: 0: line number table 2: 0/3 8/ attribute count0: attribute 1 SourceFile(#13) 0: Source file Hello.java(#14)
The Java Stack
When a new thread is launched, the JVM creates a new Java stack for the thread. It performs only two operations directly on the stack: it pushes and pops frames.
A stack frame has three parts:
- Local variables — for storing parameters and local variables; accessed by indices; no operation can be performed on them directly except iinc
- Frame data — for storing data that support constant pool resolution, normal method return, and exception dispatch.
- Operand stack — for supporting instruction execution and parameter passing; accessed by pushing and popping
Jingke Li (Portland State University) CS322 Java Virtual Machine 7 / 25
Method Invocation and Return
The JVM creats a new stack frame for each Java method invocation. The size of the frame is calculated at compile-time and stored into the class file. The actual location and layout of the stack frame are left to the implementation to decide.
- (^) Before an invocation, the caller must push the arguments (including the objectref pointer) onto its operand stack.
- The invocation instruction allocates a new stack frame, copies the arguments into the new frame’s local variable area, and switches control to the callee.
- The callee accesses the parameters from its frame’s local variable area, although it needs to push them onto its own operand stack to perform any operation. If there is a result, it needs to be pushed onto the operant stack.
- Upon returning, the result is copied from callee’s operand stack to caller’s operand stack, and the callee’s frame is popped off the stack.
Java Bytecode
Java bytecode is Java’s IR language — it is the language Java compiler (javac) compiles to and the language Java virtual machine executes.
Format: A one-byte opcode followed by zero or more operands.
- Total of 204 opcodes defined (out of 256 possible ones)
Design Goals:
- Compact form (for fast interpretation) —
- Stack-machine based — no need to specify operands in most operations iadd --- pop two integers off the operand stack; add them and push result back on the stack
- (^) Special opcodes encode frequently used operands operations iload_0 --- push const 0 to stack iload_1 --- push const 1 to stack
- Security —
- Operands are typed, with eight primitive types — byte, short, int, long, float, double, char, and reference
- Opcodes encode operands’ type iadd, fadd Jingke Li (Portland State University) CS322 Java Virtual Machine 9 / 25
Stack Pushing and Popping Instructions
- (^) Pushing constants onto the stack: iconst_m1, iconst_0, ..., iconst_ fconst_0, fconst_1, fconst_2, lconst_0, lconst_1, ... aconst_null, ... ldc1 idx1, ldc2 idx1,idx2, ldc2w idx1,idx2, ...
- Pushing/popping local variables: iload vidx, iload_0, iload_1, iload_2, iload_ istore vidx, istore_0, istore_1, istore_2, istore_ fload vidx, fload_0, fload_1, fload_2, fload_ ...
- (^) Load/store an array component onto/from the stack: baload, caload, saload, iaload, laload, ... bastore, castore, sastore, iastore, lastore, ...
- (^) General stack management: pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, swap
A Bytecode Example
"Hello.java": class Hello { public static void main(String[] a) { System.out.println("Hello World!"); } }
"Hello.class" disassembled (run ’javap -c Hello’): class Hello extends java.lang.Object{ Hello(); Code: 0: aload_ 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/Str 8: return } Jingke Li (Portland State University) CS322 Java Virtual Machine 13 / 25
Another Example
class Test { public static void main(String[] a) { int i=2, j=3; i = i + j * 4; j = (i+1) * (i-1); System.out.println(j); } } public static void main(java.lang.String[]); Code: 0: iconst_2 11: iconst_ 1: istore_1 12: iadd 2: iconst_3 13: iload_ 3: istore_2 14: iconst_ 4: iload_1 15: isub 5: iload_2 16: imul 6: iconst_4 17: istore_ 7: imul 18: getstatic #2; 8: iadd 21: iload_ 9: istore_1 22: invokevirtual #3; 10: iload_1 25: return }
A Third Example
class Fibonacci { static long nthFiboNum(int n) { long fiboNum = 1, a = 1, b = 1; for (int i=1; i<n; i++) { fiboNum = a + b; a = b; b = fiboNum; } return fiboNum; } }
static long nthFiboNum(int); Code: 0: lconst_1 10: iload 7 23: lstore_ 1: lstore_1 12: iload_0 24: lload_ 2: lconst_1 13: if_icmpge 33 25: lstore 5 3: lstore_3 16: lload_3 27: iinc 7, 1 4: lconst_1 17: lload 5 30: goto 10 5: lstore 5 19: ladd 33: lload_ 7: iconst_1 20: lstore_1 34: lreturn 8: istore 7 21: lload 5 } Jingke Li (Portland State University) CS322 Java Virtual Machine 15 / 25
Sun’s JVM Implementation
Brief History:
- (^) First Generation — Purely interpreting, 30–50 times slower than C++
- Second Generation — JIT compilers, 3–10 times slower than C++
- HotSpot (3rd generation, first released in April 1999) — Adaptive JIT’s, 2–3 times faster than 2nd generation JITs
Current Status:
- (^) HotSpot is currently supported by Sun on Microsoft Windows, Linux, and Solaris. Other ports are available by third parties.
- (^) Consists of two JVMs, one called “Client” and the other “Server.”
- (^) On 13 November 2006, the Sun HotSpot JVM and JDK were made available under the GPL license.
Just-In-Time Compilers
JIT was first used 10 years ago in commercial Smalltalk systems. Essentially the same as traditional compilers, just invoked on-the-fly:
- (^) Translate portable bytecodes to machine code
- (^) Compile on method-by-method basis when a method is first invoked
- (^) Apply traditional optimizations to improve the quality of the target code
Problem: Compilation consumes execution time
- startup latency
- optimization time
Dilemma: Good code? Or fast compiler?
Need to balance compile vs. execution time. Gains of better optimization may not justify extra compile time.
Jingke Li (Portland State University) CS322 Java Virtual Machine 19 / 25
Case Study: The HotSpot JVM
Adaptive Compilation:
- Only compile/optimize the parts that matter (the “hot spots”)
- Seamlessly transition between interpreted and compiled code as necessary
- Fast, accurate garbage collection
- Fast thread synchronization
Architecture:
interpreter^ fast compiler
bytecodedmethods compiledmethods
dynamic profiler/recompiler collectorsgarbage
Typical Scenario
- A program starts off being interpreted
- A profiler collects run-time info in the background
- After a while, a set of hot spots are identified
- A thread is launched to compile the methods in the hot spots:
- Execution of the program is not blocked
- Compiler performs full optimization: no time limit
- Take advantage of the late compilation: run-time info used
- Once a method is compiled, it does not need to be interpreted
- Native code can be discarded when the hot spots change:
- Keeping the footprint small
- Bytecode is always kept around
Jingke Li (Portland State University) CS322 Java Virtual Machine 21 / 25
HotSpot Memory Model
- (^) Uniform Object Model — Classes, methods, and other internal reflective data are all represented as objects on the heap - Simplifies the VM internal object model - Allows classes and other objects to be collected by the same GC
- Object References — via direct pointers (Previous JVM: via indirect handles - a performance boost (C speed access to instance variables) - GC must adjust all references to an object when it is relocated
- Object Headers — 2-words (Previous JVM: 3-words) - On average an 8% savings in heap size
HotSpot Optimizing Compiler
- (^) Fully Optimizing Compiler:
- Performs all the classic optimizations
- And Java-specific optimizations
- Global graph coloring register allocator
- Profile-Driven Inlining:
- Inline only the critical methods point
- (^) Dynamic Deoptimization:
- Remove a hot spot when program execution pattern changes
- Transparent Debugging and Profiling Semantics:
- Native code generation & optimization fully transparent to the programmer
- Highly Portable:
- Relying on a small machine description file