Bytecode and the JVM
Java is compiled down to bytecode, which is interpreted by the JVM (Java Virtual Machine). The JVM has to be re-implemented on every platform and handles the OS / platform specific aspects (each implementation may differ).
Java bytecode is verified for issues like illegal casts, type checks, integer to pointer conversions, etc… before being executed.
JVM
The JVM is a stack-based abstract machine. It pops and pushes values on the stack.
It can also JIT compile certain code (usually “hot” functions that are called often) to native machine code, which makes execution fast.
The JVM also handles garbage collection.
We can look into the bytecode by using javap -c Class which outputs the bytecode version of our code (Not in the exam, but useful).

Java Basics Recap
Loops
There are bounded and unbounded loops. For bounded loops, we know the amount of times it will run. An unbounded loop is often a while loop depending on user input, etc…
Parallelism and Exceptions
Exceptions are less effective with parallelism because the cause of the error may be far earlier than when it actually triggers. The stack trace is thus less useful.
Exceptions thrown in parallel threads don’t automatically reach the main thread, i.e. they might be silently ignored.
Tidbits
Java has the native keyword which allows us to load code from C/C++ or other compiled languages using dynamic linking. We can call those methods in our regular code then.
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_square(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}