Code Execution JVM

Personal notes on JVM code execution. Mostly taken from "Optimizing Java" from Benjamin J. Evans, Chris Newland and James Gough

JVM executes interpreted bytecode, instead of machine code directly which can be considered slow. In order to be increase performance, Java environments solve this problem by providing dynamic compilation, or JIT (just-in-time) compilation.

JIT

JIT is a mechanism but which the JVM monitors witch methods are being executed in order to determine whether individual methods are eligible to directly executable code. Just in time compilation is a technique whereby programs are converted into highly optimized machine code at runtime. Hotspot and most other production-grade JVMs rely heavily on this approach.

The technique gathers information about the runtime and builds a profile that can be used to determine which parts of the program are used frequently and would benefit most from optimization.

Bytecode Interpretation

The JVM interpreter operates as a stack machine. Unlike physical CPU's, there are no registers that are used as immediate holding areas for computation. Instead, all values are put in a evaluation stack, and the stack machine instructions work by transforming the values(s) at the top of the stack.

Areas to hold data:

  • Evaluation stack, which is local to a particular method

  • Local variables to temporarily store results

  • Heap - is shared between methods and between threads

JVM Bytecode

Each machine operation (opcode) is represented by 1 byte. Opcodes run from 0 to 255 (Java 10 only uses around 200).

Load and Store

Family name

Arguments

Description

load

(i1)

Loads value from local variable i1 onto the stack

store

(i1)

Stores top of stack into local variable i1

ldc

c1

Loads value from CP#c1

const

Loads simple constant value onto the stack

pop

Discards value on top of stack

dup

Duplicates value on top of stack

getfield

c1

Loads value from field CP#c1 in object on top of stack onto the stack

putfield

c1

getstatic

c1

putstatic

c1

Arithmetic

Family name

Description

add

Adds two values from top of stack

sub

Subtracts two values from top of stack

div

Divides two values from top of stack

mul

Multiplies two values from top of stack

(cast)

Casts value at top of stack to a different primitive type

neg

Negates value at top of stack

rem

Computes remainder (integer division) of top two values on stack

Flow control

Family name

Arguments

Description

if

(i1)

Branch to the location indicated by the argument

goto

i1

Unconditional branch to the supplied offset

tableswitch

lookupswitch

Method invocation

Opcode

Arguments

Description

invokevirtual

c1

Invokes the method found at CP#c1 via virtual dispatch

invokespecial

c1

Invokes the method found at CP#c1 via special dispatch

invokeinterface

c1, count, 0

Invokes the interface method found at CP#c1 using interface lookup

invokestatic

c1

Invokes the static method found at CP#c1

invokedynamic

c1, 0, 0

Dynamically looks up which method to invoke and executes it

Platform Opcodes

Opcode

Arguments

Description

new

c1

Allocates space for an object of type found at CP#c1

newarray

prim

Allocates space for a primitive array of type prim

anewarray

c1

Allocates space for an object array of type found at CP#c1

arraylength

Replaces array on top of stack with its length

monitorenter

Locks monitor of object on top of stack

monitorexit

Unlocks monitor of object on top of stack

Last updated

Was this helpful?