0% found this document useful (0 votes)
2 views29 pages

Java Virtual Machine Overview and Insights

The document discusses the Java Virtual Machine (JVM), highlighting its role in executing Java programs through an interpreter and Just-In-Time (JIT) compilation for performance optimization. It also covers memory management techniques, particularly garbage collection, which helps manage object lifecycles and memory allocation. The JVM's mechanisms enhance efficiency but can impact startup time due to class loading.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views29 pages

Java Virtual Machine Overview and Insights

The document discusses the Java Virtual Machine (JVM), highlighting its role in executing Java programs through an interpreter and Just-In-Time (JIT) compilation for performance optimization. It also covers memory management techniques, particularly garbage collection, which helps manage object lifecycles and memory allocation. The JVM's mechanisms enhance efficiency but can impact startup time due to class loading.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Advanced Programming in Java


CM2: the Java Virtual Machine (JVM)

Arthur Bit-Monnot

INSA 4IR

Arthur Bit-Monnot | INSA 4IR 1 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Java Virtual Machine: Motivation

// C: 0.87 ns / element
int max(int* ints) {
int m = 0;
for (long i = 0; i<N; i++) {
int curr = ints[i];
m = m > curr ? m : curr;
}
return m;
}

# python: 240.3 ns / element


m = 0
for i in ints:
m = max(m, i)

Arthur Bit-Monnot | INSA 4IR 2 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Java Virtual Machine: Motivation

// C: 0.87 ns / element // java (ints) 0.97 ns / element


int max(int* ints) { static int maxInt(int[] ints) {
int m = 0; int max = 0;
for (long i = 0; i<N; i++) { for (int i=0; i< [Link]; i++) {
int curr = ints[i]; max = [Link](max, ints[i]);
m = m > curr ? m : curr; }
} return max;
return m; }
}

# python: 240.3 ns / element


m = 0
for i in ints:
m = max(m, i)

Arthur Bit-Monnot | INSA 4IR 2 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Java Virtual Machine: Motivation

// C: 0.87 ns / element // java (ints) 0.97 ns / element


int max(int* ints) { static int maxInt(int[] ints) {
int m = 0; int max = 0;
for (long i = 0; i<N; i++) { for (int i=0; i< [Link]; i++) {
int curr = ints[i]; max = [Link](max, ints[i]);
m = m > curr ? m : curr; }
} return max;
return m; }
} // java (Integer) 2.68 ns / element
static Integer maxInteger(Integer[] ints) {
# python: 240.3 ns / element int max = 0;
m = 0 for (int i=0; i< [Link]; i++) {
for i in ints: max = [Link](max, (int) ints[i]);
m = max(m, i) }
return max;
}
The JVM is what explains 90% of the difference between Java and Python.

Arthur Bit-Monnot | INSA 4IR 2 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Compiling a java program

javac: the Java Compiler


javac [Link]
produces one .class file for each java class in the source file
[Link]
Json$[Link]
Json$[Link]

Note: sometime java projects are compiled as a .jar file:


simply a zip file containing .class files !

Arthur Bit-Monnot | INSA 4IR 3 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

Class files & Java Bytecode


Each class file contains the description of the class in a binary format that is easily consumed
by machines
java classfile (human readable view)

the class metadata


implemented classes and interfaces
all class attributes
all provided methods

The java source code in the methods in


translated to java bytecode.

Arthur Bit-Monnot | INSA 4IR 4 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

The Java Bytecode

java bytecode (human readable view)

Instruction set of the JVM


Build for efficient machine analysis
Closely matches the Java language

All languages running on the JVM are


compiled to java bytecode
Java, Scala, Kotlin, Clojure, . . .

Arthur Bit-Monnot | INSA 4IR 5 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM)

The java Runtime

java Json --class-path .


> {x: 10,y: 34,}
> [{x: 10,y: 23,}, {x: 1,y: 2,}, ]
> {start: {x: 10,y: 23,},end: {x: 1,y: 2,},}

The java command starts a Java application. It does this by starting the Java Virtual
Machine (JVM), loading the specified class, and calling that class’s ‘main()“ method.

Json : name of the class to execute


--class-path . : path to the compiled class files

Arthur Bit-Monnot | INSA 4IR 6 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Section 1

Executing Java programs: Interpreter & JIT Compiler

Arthur Bit-Monnot | INSA 4IR 7 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Class loading

Upon starting, the JVM will start by loading the necessary classes
starting from the main class (specified on the command line)
recursively loading all classes it encounters

If a class is not found in the classpath, it throws ClassNotFoundException and exits.


indicates that the classpath is wrong

After this phase, all the code necessary for your program to run is available in the memory
(RAM, in the JVM process).

Arthur Bit-Monnot | INSA 4IR 8 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

The interpreter

Problem: java bytecode != CPU


instruction set
not immediately executable

Arthur Bit-Monnot | INSA 4IR 9 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

The interpreter

dummy bytecode interpreter


for ever
Problem: java bytecode != CPU inst := load_next_instruction
instruction set if inst == "i_load"
not immediately executable value := read_from_ram(...)
push(value)
The java bytecode is interpreted: elif inst == "i_add"
a program reads the bytecode the v1 := pop()
bytecode line by line and simulates its v2 := pop()
executation result := v1 + v2
push(result)
...

Arthur Bit-Monnot | INSA 4IR 9 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Beyond Interpreters: the JIT Compiler

Problem of interpreters: they are slooooow


easily 10x slower than optimized machine code

Just In Time (JIT) compilation:


if a method is called more than a given threshold,
compile to efficient machine code (x86, ARM, . . . )

Arthur Bit-Monnot | INSA 4IR 10 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Advantages of JIT compilers

by compiling at the last possible moment, the JVM knows a lot about current program
precise architecture of the current machine
statistics on the method currently executed
number of invocation of methods
actual class of the parameters
branches taken

The interpreter plays a crucial role in gathering the statistics for a more efficient compilation!
(profiling)

Arthur Bit-Monnot | INSA 4IR 11 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Advantages of JIT: Optimistic Optimization & De-Optimization

Very often, profiling suggests very interesting optimizations

“So far, the toJson method has ALWAYS been called with the Point class as param-
eter”
Optimistic Optimization:
compile as if your assumption was always true, (toJson will always be called with Point)
enables many optimizations

Arthur Bit-Monnot | INSA 4IR 12 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

Advantages of JIT: Optimistic Optimization & De-Optimization

Very often, profiling suggests very interesting optimizations

“So far, the toJson method has ALWAYS been called with the Point class as param-
eter”
Optimistic Optimization:
compile as if your assumption was always true, (toJson will always be called with Point)
enables many optimizations
at the beginning of the generated code, add a check that your assumption hold (a guard)
if the check fails, throw away the compiled code and go back to the interpreter
(de-optimization)
you can later recompile with the additional information (e.g. toJson is called with Point
97% of the time)

Arthur Bit-Monnot | INSA 4IR 12 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Executing Java programs: Interpreter & JIT Compiler

In other languages1

Language Pre-compiled Interpreted Interpreted + JIT Compiled


Java X
C / C++ X
Python X
Javascript X
Rust X
Go X
Bash X

1
In main implementation. For instance, PyPy provides a JIT for python but is incompatible with a large part
of the ecosystem.
Arthur Bit-Monnot | INSA 4IR 13 / 24
Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Section 2

Memory Management: Garbage Collection

Arthur Bit-Monnot | INSA 4IR 14 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management: Garbage Collection

void allocatingMethod() {
var n = new Integer(11);
doSomething(n);
}
What happened to the memory allocated for n ?

Arthur Bit-Monnot | INSA 4IR 15 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management not always trivial

// pushed to a data structure


// that outlives the method
void allocatingMethod(
List<Integer> collection)
{ // nested in a more complex datastructure
var n = new Integer(11); Point allocatingMethod() {
[Link](n); var x = new Integer(11);
} var y = new Integer(14);
var point = new Point(x, y);
// sent to another thread return point;
void allocatingMethod() { }
var n = new Integer(11);
Thread t = new MyThread(n)
[Link]();
}

Arthur Bit-Monnot | INSA 4IR 16 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management Approaches: Manual Management

Let the programmer decide when to deallocate

int * onHeapInt = malloc(sizeof(int));


... Endless source of bugs and security
free(onHeapInt); issues
memory leaks (not freed)
use after free
Taken historically by low-level languages (C) double free
most powerful and potentially efficient

Arthur Bit-Monnot | INSA 4IR 17 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management Approaches: Reference Counting

Principle: in every object header, add a counter that keeps track of the number of references
to this object
each time a reference is copied: increment the counter
each time a reference goes out of scope: decrement the counter
if the counter reaches 0, deallocate the object

Arthur Bit-Monnot | INSA 4IR 18 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management Approaches: Reference Counting

Principle: in every object header, add a counter that keeps track of the number of references
to this object
each time a reference is copied: increment the counter
each time a reference goes out of scope: decrement the counter
if the counter reaches 0, deallocate the object
Problems:
each time a reference is copied/deleted an atomic increment must be made to the
object counter! (costly)
if there is a cycle of references, the memory will not be freed (memory leak)

Adopters: Python, Swift, C++ (with smart pointers)

Arthur Bit-Monnot | INSA 4IR 18 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management Approaches: Tracing Garbage Collector


(Basic) Approach: at regular intervals
stop the program
mark: from the references on the stack, recursively follow all references and mark all
objects you encounter
sweep: go through the entire program’s memory and remove all objects that are not
marked
resume the program

General principle: tracing garbage collection (GC) (here with the mark-and-sweep
algorithm).
introduced by Lisp in 1959 (xkcd/297)
adopters: Java, JavaScript, Go

Arthur Bit-Monnot | INSA 4IR 19 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management Approaches: Tracing Garbage Collector

GC much more evolved nowadays:


concurrent: no stopping for marking / sweeping
compacting: reorganize allocated memory on sweep (require stopping)
generational: differentiated handling of short-lived / long-lived objects
Nowadays:
robust and correct
very efficient: throughput comparable with manual memory management2
gained by compaction: make memory cache-firendly and allocations trivial
downsides:
cpu hoverhead (low)
memory overhead (significant)
short program pauses: impacts worse-case latency
2
of course, manual management offers more opportuinities for optimization
Arthur Bit-Monnot | INSA 4IR 20 / 24
Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Memory Management: Garbage Collection

Memory Management: Languages Status

Language Manual Ref-counted Tracing GC


Java X
C / C++ X
Python X X
Javascript X
Go X
OCaml X
Swift X
Rust3

3
compiler enforces and tracks a single owner for each object. Correct and with no overhead !!!
Arthur Bit-Monnot | INSA 4IR 21 / 24
Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Summary

Section 3

Summary

Arthur Bit-Monnot | INSA 4IR 22 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Summary

Summary

The JVM has several mechanisms to make java programs efficient and convenient:
Interpreter + JIT compiler
reach peak performance

Garbage Collection
Analysis references to objects to decide when to deallocate an object
optimize memory allocations

Arthur Bit-Monnot | INSA 4IR 23 / 24


Advanced Programming in Java CM2: the Java Virtual Machine (JVM) | Summary

Downsides
class loading impacts the startup time of the JVM
can be a few seconds for programs with huge dependencies
it takes time to reach peak performance
requires runtime analysis + JIT compilation
GC requires to stop the program regularly
may induce latencies
important memory consumption overhead (GC + class loading)

Java is not suitable for every task


heavily used in server environments for long-running tasks
unsuitable in applications where:
memory is scarce (embedded)
require fine-grained memory control (OS/drivers)
are very short-lived (command line tools)
Arthur Bit-Monnot | INSA 4IR 24 / 24

You might also like