Inside the JVM: How Java Works Under the Hood