Java Bytecode What is a .class file anyway? Dan Fleck George Mason University Fall 2007 What is in a .class file? Create source file Compile source file into .class file Run the .class file So, what is in the .class file? The way other languages work (C, ADA, etc…) Source code is written Source code is ported to every different platform Source code is compiled into platform specific machine code (or binaries) Binaries execute on a single platform Source Code Linux port Windows port Mac port Linux Compile Windows Compile Mac Compile Linux binary Win binary Mac binary Linux Machine Windows Machine Mac Machine Java: Write once, compile, run anywhere! Java is compiled into machine independent bytecode class files Bytecode is interpreted by the Java Virtual Machine (JVM) JVM executes the step-by-step instructions given to it from the bytecode JVM is specific to each computer architecture (Linux JVM, Windows JVM, Mac JVM). How Java Does it Source Code Java Compile Linux JVM Win JVM Mac JVM Linux Machine Windows Machine Mac Machine Advantages of Bytecode Bytecode is architecture independent (and writing a VM is easier than rewriting a compiler for every architecture) VMs can enforce different levels of security automatically (applets versus applications) Just In-Time (JIT) compiling helps achieve same or better speed than traditional compiled code Other languages that have an intermediate representation C# Perl PHP Python Forth Tcl Java Bytecode Stack-based virtual machine Small instruction set: 202 instructions (all are 1 byte opcode + operands) Intel x86: ~280 instructions (1 to 17 bytes long!) Memory is typed Every Java class file begins with magic number 3405691582 = 0xCAFEBABE Referencing Memory iload <varnum> istore <varnum> Pops the int on the top of the stack and stores it in local variable <varnum> iload, fload, dload, aload (reference) istore, fstore, dstore, astore Pushes (loads) the int in local variable <varnum> (1 bytes) on the stack Javap examples javac -g Test1.java public class Test1 { public int add(int a, int b) { int c= a+b; return c; } } javap -c Test1 … public int add(int, int); Code: 0: iload_1 // push onto stack 1: iload_2 // push onto stack 2: iadd // add var 1 and 2 3: istore_3 // store as local var 3 4: iload_3 // store onto stack 5: ireturn // return int Javap included with Java Development Kit (JDK) JAD example javac -g Test1.java public class Test1 { public int add(int a, int b) { int c= a+b; return c; } } jad -a Test1 … public int add(int a, int b) { int c = a + b; // 0 0:iload_1 // 1 1:iload_2 // 2 2:iadd // 3 3:istore_3 return c; // 4 4:iload_3 // 5 5:ireturn } JAD is free, but not included with Java Development Kit (JDK) Java Bytecode Explanation Opcode Mnemonic Description 0 nop Does nothing 1 aconst_null Push null on the stack 3 iconst_0 Push int 0 on the stack 4 iconst_1 Push int 1 on the stack … Java Bytecode Explanation Opcode 18 Mnemonic ldc <value> Description Push a one-word (4 bytes) constant onto the stack Constant may be an int, float or String ldc “Hello” ldc 201 The String is really a reference to an entry in the string constant table! Java Bytecode Arithmetic Opcode 96 Mnemonic iadd Description Pops two integers from the stack and pushes their sum iconst_2 iconst_3 iadd Java Bytecode Arithmetic Opcode Mnemonic Description 96 iadd Pops two integers from the stack and pushes their sum 97 ladd Pops two long integers from the stack and pushes their sum fmul Pops two floats from the stack and pushes their product dneg Pops a double from the stack, and pushes its negation … 106 … 119 Other types of Instructions Control Flow (~20 instructions) if, goto, return Method Calls (4 instructions) Loading and Storing Variables (65 instructions) Creating objects (1 instruction) Using object fields (4 instructions) Arrays (3 instructions) Method Calls invokevirtual <method> Invokes the method <method> on the parameters and object on the top of the stack. Finds the appropriate method at run-time based on the actual type of the this object. invokevirtual <Method void println(java.lang.String)> Control Flow ifeq <label> Pop an int off the stack. If it is zero, jump to the label. Otherwise, continue normally. if_icmple <label> Pop two ints off the stack. If the second one is <= the first one, jump to the label. Otherwise, continue normally. Static Method Calls invokestatic <method> Invokes a static (class) method <method> on the parameters on the top of the stack. Finds the appropriate method at run-time based on the actual type of the this object. JAD example 2 javac -g Test1.java public void count() { for (int i=0; i<10; i++) { System.out.println( "i is "+i); } } VM Spec: http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html public void count() { for(int i = 0; i < 10; i++) //* 0 0:iconst_0 //* 1 1:istore_1 //* 2 2:iload_1 //* 3 3:bipush 10 //* 4 5:icmpge 39 System.out.println((new StringBuilder()).append("i is ").append(i).toString()); // 5 8:getstatic #2 <Field PrintStream System.out> // 6 11:new #3 <Class StringBuilder> // 7 14:dup // 8 15:invokespecial #4 <Method void StringBuilder()> // 9 18:ldc1 #5 <String "i is "> // 10 20:invokevirtual #6 <Method StringBuilder StringBuilder.append(String)> // 11 23:iload_1 // 12 24:invokevirtual #7 <Method StringBuilder StringBuilder.append(int)> // 13 27:invokevirtual #8 <Method String StringBuilder.toString()> // 14 30:invokevirtual #9 <Method void PrintStream.println(String)> JAD example JAD example 3: Test2.java What does this method do? // // // // // // // // // // 0 0:iconst_5 1 1:istore_1 2 2:bipush 3 4:istore_2 4 5:iload_2 5 6:iload_1 6 7:isub 7 8:istore_3 8 9:iload_3 9 10:ireturn 10 JAD example 3: Test2.java What does this method do? // // // // // // // // // // 0 0:iconst_5 1 1:istore_1 2 2:bipush 3 4:istore_2 4 5:iload_2 5 6:iload_1 6 7:isub 7 8:istore_3 8 9:iload_3 9 10:ireturn Push 5 onto stack Store into local var 1 10 Push 10 onto stack Store into local var 1 Load var 2 onto stack Load var 1 onto stack Subtract stack vars Store into local var 1 Load var 3 onto stack Return (top val from stack) JAD example 3: Test2.java public int subtract() { int a = 5; // 0 0:iconst_5 // 1 1:istore_1 int b = 10; // 2 2:bipush // 3 4:istore_2 int c = b - a; // 4 5:iload_2 // 5 6:iload_1 // 6 7:isub // 7 8:istore_3 return c; // 8 9:iload_3 // 9 10:ireturn } 10 References http://ocw.mit.edu/NR/rdonlyres/Special-Programs/SP-772Spring-2005Summer-2005/3AFB411F-B5C0-4032-9964-BF733EEB3199/0/bytecode.pdf http://www.cs.virginia.edu/evans, Bytecode, Lecture 18