CSE 431S Java Virtual Machine

Post on 03-Feb-2022

10 views 0 download

Transcript of CSE 431S Java Virtual Machine

CSE 431S Java Virtual Machine

Washington University

Spring 2013

Java Virtual Machine

• What is it?

– Platform independent

– Stack based

– Field and methods are referenced by name

– Instructions for int, long, float, and double

– No direct support for byte, short, or char types

• Handled by int operations and type conversion

Generic Process

Threads Single-Threaded Process Model

Multithreaded Process Model

User Stack

Kernel Stack

User Address Space

Process Control Block

UID, GID

Thread Control Block

User Stack

Kernel Stack

User Address Space

Process Control Block

Thread

Thread Control Block

User Stack

Kernel Stack

Thread

Thread Control Block

User Stack

Kernel Stack

Thread UID, GID

Heap

• Pool of memory (not a data structure)

• Holds non-local values

• Allocation using “malloc” or “new”

• Explicit (“free”) or implicit (garbage collection) de-allocation based on language

• Fragmentation

JVM Stack

• x86 is register based

• JVM is stack based – No registers

• Operand stack

• Commands (instructions) – Push values onto stack

– Perform operations on the values on the stack

– Pop values from the stack

• Every method call gets its own stack

Java Bytecode

• Instructions that the JVM executes

• Each opcode is 1 byte in length

• 0x00 - 0xca, 0xfe, and 0xff are assigned values.

– 0xca is reserved as a breakpoint instruction for debuggers and is not used by the language

– 0xfe and 0xff are not used by the language, and are reserved for internal use by the virtual machine.

Categories

• Load and store (e.g. aload_0, istore)

• Arithmetic and logic (e.g. ladd, fcmpl)

• Type conversion (e.g. i2b,d2i)

• Object creation and manipulation (new, putfield)

• Operand stack management (e.g. swap,dup2)

• Control transfer (e.g. ifeq, goto)

• Method invocation and return (e.g. invokespecial, areturn)

Instruction Prefix/Suffix

Prefix/Suffix Operand Type

i integer

l long

s short

b byte

c character

f float

d double

a reference

x86 vs Java bytecode

x86

add eax, edx

mov ecx, eax

Java bytecode

0 iload_1

1 iload_2

2 iadd

3 istore_3

Java Class Files

• Binary files containing Java bytecode

• Each class is compiled into one “.class” file

– if a source file has more than one class in it, each class gets its own class file

• Class files are platform independent and can run on any JVM

Java Class File Layouts

• 10 sections

– Magic Number: 0xCAFEBABE

– Version of Class File Format: the minor and major versions of the class file

– Constant Pool: Pool of constants for the class

– Access Flags: for example whether the class is abstract, static, etc.

– This Class: The name of the current class

– Super Class: The name of the super class

Java Class File Layouts

– Interfaces: Any interfaces in the class

– Fields: Any fields in the class

– Methods: Any methods in the class

– Attributes: Any attributes of the class (for example the name of the sourcefile, etc.)

My Very Cute Animal Turns Savage In Full Moon Areas

Origins of a Magic Number

James Gosling:

We used to go to lunch at a place called St Michael's…

We referred to the place as Cafe Dead. …it was noticed that this was a HEX number. …

I used CAFEDEAD for the object file format, and in grepping for 4 character hex words that fit after "CAFE" (it seemed to be a good theme) I hit on BABE and decided to use it…

CAFEBABE became the class file format, and CAFEDEAD was the persistent object format… - it was eventually replaced by RMI.

Primitive Types

• Primitive types are represented by one of the following characters:

Type Character

Byte B

Char C

Double D

Float F

Int I

Long J

Short S

boolean Z

Constant Pool

• Stores literal constant values

– numbers of all sorts

– strings

– identifier names

– references to classes and methods

– type descriptors

• Referenced by 16 bit numbers

• 1 is the first entry

Descriptors

• Classes – Classes are indicated by an 'L', followed by the path to the

class name, then a semi-colon to mark the end of the class name.

– For instance, a String field would have a descriptor of "Ljava/lang/String;“

• Arrays – Arrays are indicated with a '[' character. – For instance an array of Integers would have a descriptor

of "[I". – Multi-dimensional arrays simply have extra '[' characters. – For instance, "[[I".

Descriptors

• Field Descriptors – A field has just one type, described in a string in the above

notation. e.g. "I", or "Ljava/lang/String".

• Method Descriptors – Because methods involve several types - the arguments

and the return type - their type descriptor notation is slightly different. The argument types are at the start of the string inside brackets, concatenated together. Note that the type descriptors are concatenated without any separator character. The return type is after the closing bracket.

– For instance, "int someMethod(long lValue, boolean bRefresh);" would have a descriptor of "(JZ)I".

Method Names

foo/baz/Myclass/myMethod(Ljava/lang/String;)V

Class Method Descriptor

Load and Store Instructions

• iload <local variable number> – Pushes the value of the local variable which is an integer.

(..... »»»» .....value)

• istore <local variable number> – Pops the value which is an integer and stores it in local variable.

(.....value »»»» ......)

• fload <local variable number> – Pushes the value of the local variable which is a float.

(..... »»»» ......value)

• fstore <local variable number> – Pops the value which is a float and stores it in local variable.

(.....value »»»» ......)

• ldc <constant> – Push constant on the stack.

(..... »»»» .....constant)

Stack Manipulation Instructions

• dup – The word on top of the stack is duplicated.

(.....word »»»» .....word word)

• pop – Pop top word off the operand stack.

(.....word »»»» .....)

• swap – Swap two operand stack words.

(.....word1 word2 »»»» .....word2 word1)

Arithmetic Instructions

• iadd – Add two integers.

(.....value1 value2 »»»» .....value1+value2)

• idiv – Divide two integers.

(.....value1 value2 »»»» .....value1/value2)

• imul – Multiply two integers.

(.....value1 value2 »»»» .....value1*value2)

• isub – Subtract two integers.

(.....value1 value2 »»»» .....value1-value2)

Arithmetic Instructions

• fadd – Add two floats.

(.....value1 value2 »»»» .....value1+value2)

• fdiv – Divide two floats.

(.....value1 value2 »»»» .....value1/value2)

• fmul – Multiply two floats.

(.....value1 value2 »»»» .....value1*value2)

• fsub – Subtract two floats.

(.....value1 value2 »»»» .....value1-value2)

Branch Instructions

• goto <label> – Jump to label.

(no changes in stack)

• ifeq <label> – Jump to label if the value on top of stack is 0.

(.....value »»»» .....)

• ifge <label> – Jump to label if the value on top of the stack is grater than or

equal to 0. (.....value »»»» .....)

• ifgt <label> – Jump to label if the value on top of the stack is grater than 0.

(.....value »»»» .....)

Logical Instructions

• iand

– Bitwise AND (conjunction) of two integers. (.....value1 value2 »»»» .....result)

• ior

– Bitwise OR (disjunction) of two integers. (.....value1 value2 »»»» .....result)

Conversion Instructions

• i2f

– Convert integer to float. (.....intValue »»»» .....floatValue)

• f2i

– Convert float to integer. (.....floatValue »»»» .....intValue)

Subroutine Instructions

• jsr <label>

– Pushes the return address on the stack and jumps to subroutine indicated by the label. (..... »»»» .....returnAddress)

• ret <local variable number>

– Returns from subroutine to the return address which is stored in a local variable. (no changes in stack)

Method Invocation Instructions

• invokevirtual – Invokes an instance method of an object, dispatching on the

(virtual) type of the object. – This is the normal method dispatch in the Java programming

language

• invokeinterface – Invokes a method that is implemented by an interface

• invokespecial – Invokes an instance method requiring special handling – Instance initialization method, a private method, or a superclass

method

• invokestatic – Invokes a class (static) method

Method Invocation

Stack Frame

#1 (Foo)

Constant Pool

Local Variable Table

Operand Stack

Heap

Method Invocation

Stack Frame

#1 (Foo)

Constant Pool

Local Variable Table

Operand Stack

Stack Frame

#2 (Bar) Local Variable Table

Operand Stack

Heap

Method Invocation

Stack Frame

#1 (Foo)

Constant Pool

Local Variable Table

Operand Stack

Stack Frame

#2 (Bar) Local Variable Table

Operand Stack

Stack Frame

#2 (toString) Local Variable Table

Operand Stack

Heap

Method Return

Stack Frame

#1 (Foo)

Constant Pool

Local Variable Table

Operand Stack

Stack Frame

#2 (Bar) Local Variable Table

Operand Stack

Stack Frame

#2 (toString) Local Variable Table

Operand Stack

Heap

Method Return

Stack Frame

#1 (Foo)

Constant Pool

Local Variable Table

Operand Stack

Stack Frame

#2 (Bar) Local Variable Table

Operand Stack

Heap

Branch Instructions

• ifle <label> – Jump to label if the value on top of the stack is less

than or equal to 0. (.....value »»»» .....)

• iflt <label> – Jump to label if the value on top of the stack is less

than 0. (.....value »»»» .....)

• ifne <label> – Jump to label if the value on top of the stack is not

equal to 0. (.....value »»»» .....)

Local Variable Instructions

• ret <var-num> • aload <var-num> • astore <var-num> • dload <var-num> • dstore <var-num> • fload <var-num> • fstore <var-num> • iload <var-num> • istore <var-num> • lload <var-num> • lstore <var-num>

Branch Instructions

• goto <label>

• goto_w <label>

• if_acmpeq <label>

• if_acmpne <label>

• if_icmpeq <label>

• if_icmpge <label>

• if_icmpgt <label>

• if_icmple <label>

• if_icmplt <label>

• if_icmpne <label>

• ifeq <label>

• ifge <label>

• ifgt <label>

• ifle <label>

• iflt <label>

• ifne <label>

• ifnonnull <label>

• ifnull <label>

• jsr <label>

• jsr_w <label>

Class and Object Operations

• anewarray <class>

• checkcast <class>

• instanceof <class> new<class>

• Example:

new java/lang/String; create a new String object

Method Invocation

• invokenonvirtual <method-spec>

• invokestatic<method-spec>

; invokes java.io.PrintStream.println(String);

invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V

Field Manipulation

• getfield <field-spec> <descriptor>

• getstatic <field-spec> <descriptor>

• putfield <field-spec> <descriptor>

• putstatic <field-spec> <descriptor>

• Example

; get java.lang.System.out, which is a PrintStream

getstatic java/lang/System/out Ljava/io/PrintStream;

Array Instruction

• newarray <array-type>

• multianewarray <array-descriptor> <num-dimensions>

• Example

newarray int

multianewarray [[[I 2

bipush, sipush, iinc

• bipush <int>

• sipush <int>

• iinc <var-num> <amount>

• Example

bipush 100 ; push 100 onto the stack

iinc 3 -10 ; subtract 10 from local variable 3

ldc and ldc_w

• ldc <constant>

• ldc_w <constant>

• Example

ldc 1.2 ; push a float

ldc 10 ; push an int

ldc "Hello World" ; push a String

ldc_w 3.141592654 ; push PI as a double

lookupswitch

• <lookupswitch> ::=

lookupswitch

<int1> : <label1>

<int2> : <label2>

...

default : <default-label>

lookupswitch example

lookupswitch 3 : Label1 5 : Label2 default : DefaultLabel Label1: ... got 3 Label2: ... got 5 DefaultLabel: ... got something else

tableswitch

<tableswitch> ::=

tableswitch <low>

<label1>

<label2>

... default : <default-label>

Other Java Compilers

• Jikes (Java to Java bytecode) IBM/C++

• Espresso (Java to Java bytecode) Java 1.0 only

• GCJ (Java to Java bytecode) GNU Compiler

• Jasmin (Text description to Java bytecode)

• Jamaica (Macro assembly language)

• JRuby and Jython

• Groovy

• Scala (type-safe, general purpose language supporting OO and functional programming)

• JGNAT and AppletMagic (Ada to Java bytecode)

• Clojure

Sample Java File

public class FunWithNames {

private int ThisIsA_VariableName;

public void ThisIsA_MethodName (String ThisIsA_ParameterName) {

String x = "This is a literal string";

}

}

Constant Pool

const #1 = Method #4.#15; // java/lang/Object."<init>":()V const #2 = String #16; // This is a literal string const #3 = class #17; // FunWithNames const #4 = class #18; // java/lang/Object const #5 = Asciz ThisIsA_VariableName; const #6 = Asciz I; const #7 = Asciz <init>; const #8 = Asciz ()V; const #9 = Asciz Code; const #10 = Asciz LineNumberTable; const #11 = Asciz ThisIsA_MethodName; const #12 = Asciz (Ljava/lang/String;)V; const #13 = Asciz SourceFile; const #14 = Asciz FunWithNames.java; const #15 = NameAndType #7:#8;// "<init>":()V const #16 = Asciz This is a literal string; const #17 = Asciz FunWithNames; const #18 = Asciz java/lang/Object;

Hello World :: Source

public class HelloWorld {

public static void main(String[] args) {

System.out.println("Hello World!");

}

}

Hello World :: Compilation

• javac HelloWorld.java

• Java compiler converts Java source code into Java bytecode

• Output is stored in binary HelloWorld.class

• Bytecode can be viewed using:

– javap –c HelloWorld

Hello World :: Bytecode

Compiled from "HelloWorld.java" public class HelloWorld extends java.lang.Object{ public HelloWorld(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()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/String;)V 8: return }

Superclass

Constructor

main

Hello World :: Jasmin

.class public HelloWorld

.super java/lang/Object .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .end method .method public static main([Ljava/lang/String;)V .limit stack 2 getstatic java/lang/System/out Ljava/io/PrintStream ldc "Hello World!" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V return .end method

Jasmin

• Java Assembler Interface

• Creates binary Java classes

– ASCII descriptions

– simple assembler-like syntax

• Minimal compile time checks

– Doesn’t check for existence of referenced classes

– Doesn’t check for well formed type descriptors

• No optimization

Hello World :: Jasmin

.class public HelloWorld

.super java/lang/Object ; ; standard initializer (calls java.lang.Object's initializer) ; .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return.end method ; ; main() - prints out Hello World ; .method public static main([Ljava/lang/String;)V .limit stack 2 ; up to two items can be pushed ; push System.out onto the stack getstatic java/lang/System/out Ljava/io/PrintStream ; ; push a string onto the stack ldc "Hello World!“ ; call the PrintStream.println() method. invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V ; done return .end method

Building Java classes from Jasmin

• java –jar jasmin.jar HelloWorld.j

• Executes the jar file “jasmin.jar” containing the Jasmin code

• Passes a single parameter “HelloWorld.j”

HelloWorld (Jasmin) :: Bytecode

Compiled from "HelloWorld.j" public class HelloWorld extends java.lang.Object{ public HelloWorld(); Code: 0: aload_0 1: invokespecial #21; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #20; //Field java/lang/System.out:Ljava/io/PrintStream 3: ldc #10; //String Hello World! 5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }

What’s in jasmin.jar?

• META-INF/ • META-INF/MANIFEST.MF • jas/AnnotDefAttr.class • jas/AnnotParamAttr.class • jas/Annotation.class • jas/AnnotationAttr.class • jas/AnnotationElement.class • jas/AsciiCP.class • jas/ByteOperand.class • jas/CP.class • jas/CPOperand.class • jas/CatchEntry.class • jas/Catchtable.class • …

• jas/InsnOperand.class

• jas/IntegerCP.class

• jas/IntegerOperand.class

• jas/InterfaceCP.class

• jas/InvokeinterfaceInsn.class

• jas/InvokeinterfaceOperand.class

• jas/Method.class

• jas/MethodCP.class

• jas/MultiarrayInsn.class

• jas/MultiarrayOperand.class

• …

What’s in jasmin.jar?

• jasmin/CUP$actions.class • jasmin/ClassFile.class • jasmin/InsnInfo.class • jasmin/Main.class • jasmin/ReservedWords.class • jasmin/Scanner.class • jasmin/ScannerUtils.class • jasmin/num_token.class • jasmin/parser.class • jasmin/relative_num_token.class • jasmin/sym.class • jasmin/var_token.class • java_cup/

• java_cup/runtime/ • java_cup/runtime/char_token.class • java_cup/runtime/double_token.class • java_cup/runtime/float_token.class • java_cup/runtime/int_token.class • java_cup/runtime/long_token.class • java_cup/runtime/lr_parser.class • java_cup/runtime/str_token.class • java_cup/runtime/symbol.class • java_cup/runtime/token.class • java_cup/runtime/virtual_parse_stack.

class

Factorial

public class Factorial { public static void main(String[] args) { Factorial f = new Factorial(); int i = Integer.parseInt(args[0]); System.out.println(i+"!="+ f.doFactorial(i)); } public int doFactorial(int i) { if (i==1) { return 1; } else { return i*doFactorial(i-1); } } }

Factorial Bytecode

Compiled from "Factorial.java"

public class Factorial extends java.lang.Object{

public Factorial();

Code:

0: aload_0

1: invokespecial #1; //Method java/lang/Object."<init>":()V

4: return

Factorial Bytecode

public static void main(java.lang.String[]); Code: 0: new #2; //class Factorial 3: dup 4: invokespecial #3; //Method "<init>":()V 7: astore_1 8: aload_0 9: iconst_0 10: aaload 11: invokestatic #4; //Method

java/lang/Integer.parseInt:(Ljava/lang/String;)I 14: istore_2 15: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 18: new #6; //class java/lang/StringBuilder 21: dup 22: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V

Factorial Bytecode

25: iload_2

26: invokevirtual #8; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

29: ldc #9; //String !=

31: invokevirtual #10; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

34: aload_1

35: iload_2

36: invokevirtual #11; //Method doFactorial:(I)I

39: invokevirtual #8; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

42: invokevirtual #12; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

45: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

48: return

Factorial Bytecode

public int doFactorial(int); Code: 0: iload_1 1: iconst_1 2: if_icmpne 7 5: iconst_1 6: ireturn 7: iload_1 8: aload_0 9: iload_1 10: iconst_1 11: isub 12: invokevirtual #11; //Method doFactorial:(I)I 15: imul 16: ireturn }

Factorial Constant Pool

Constant pool:

const #1 = Method #14.#26; // java/lang/Object."<init>":()V

const #2 = class #27; // Factorial

const #3 = Method #2.#26; // Factorial."<init>":()V

const #4 = Method #28.#29; // java/lang/Integer.parseInt:(Ljava/lang/String;)I

const #5 = Field #30.#31; // java/lang/System.out:Ljava/io/PrintStream;

const #6 = class #32; // java/lang/StringBuilder

const #7 = Method #6.#26; // java/lang/StringBuilder."<init>":()V

const #8 = Method #6.#33; // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

const #9 = String #34; // !=

const #10 = Method #6.#35; // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

const #11 = Method #2.#36; // Factorial.doFactorial:(I)I

const #12 = Method #6.#37; // java/lang/StringBuilder.toString:()Ljava/lang/String;

Factorial Constant Pool

const #13 = Method #38.#39; // java/io/PrintStream.println:(Ljava/lang/String;)V

const #14 = class #40; // java/lang/Object

const #15 = Asciz <init>;

const #16 = Asciz ()V;

const #17 = Asciz Code;

const #18 = Asciz LineNumberTable;

const #19 = Asciz main;

const #20 = Asciz ([Ljava/lang/String;)V;

const #21 = Asciz doFactorial;

const #22 = Asciz (I)I;

Factorial Constant Pool

const #23 = Asciz StackMapTable; const #24 = Asciz SourceFile; const #25 = Asciz Factorial.java; const #26 = NameAndType #15:#16;// "<init>":()V const #27 = Asciz Factorial; const #28 = class #41; // java/lang/Integer const #29 = NameAndType #42:#43;// parseInt:(Ljava/lang/String;)I const #30 = class #44; // java/lang/System const #31 = NameAndType #45:#46;// out:Ljava/io/PrintStream; const #32 = Asciz java/lang/StringBuilder; const #33 = NameAndType #47:#48;// append:(I)Ljava/lang/StringBuilder; const #34 = Asciz !=; const #35 = NameAndType #47:#49;// append:(Ljava/lang/String;)Ljava/lang/StringBuilder; const #36 = NameAndType #21:#22;// doFactorial:(I)I const #37 = NameAndType #50:#51;// toString:()Ljava/lang/String; const #38 = class #52; // java/io/PrintStream

Factorial Constant Pool

const #39 = NameAndType #53:#54;// println:(Ljava/lang/String;)V const #40 = Asciz java/lang/Object; const #41 = Asciz java/lang/Integer; const #42 = Asciz parseInt; const #43 = Asciz (Ljava/lang/String;)I; const #44 = Asciz java/lang/System; const #45 = Asciz out; const #46 = Asciz Ljava/io/PrintStream;; const #47 = Asciz append; const #48 = Asciz (I)Ljava/lang/StringBuilder;; const #49 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuilder;; const #50 = Asciz toString; const #51 = Asciz ()Ljava/lang/String;; const #52 = Asciz java/io/PrintStream; const #53 = Asciz println; const #54 = Asciz (Ljava/lang/String;)V;