Java Deep Dive Test
Anyone can drive a car. A mechanic can also tell you why it pulls to the left when you brake, and what will break next if you ignore it. This test is for the Deep Dive track, and it asks the mechanic's questions. It is not about syntax. It asks how the JIT compiles your code, what the memory model promises between threads, what the bytecode looks like, and how HashMap and the garbage collectors work inside.
How the Test Works
- What's in it: 20 multiple-choice questions, then 3 puzzles where you work out what a short program prints or what can go wrong.
- Time: 30 minutes, without notes, an IDE or JShell.
- Pass mark: 16 out of 23. The quiz marks the 20 questions for you. Mark the puzzles yourself, one point each, and add them to your quiz score.
- What it covers: the JIT, the Java Memory Model, lock-free code, bytecode, collection internals, garbage collection and the newest JVM features. Start with JVM Architecture Overview if these topics are new to you.
Part 1: 20 Questions
Part 2: Puzzles
Work out each answer on paper before you open the solution. The solution shows a full program, its real output and a Try it button. Give yourself one point for each puzzle you get right.
Puzzle 1: A Flag Without Volatile
What can happen when these two threads run? How do you fix it?
static boolean ready = false; // not volatile
static int value = 0;
// Thread 1
value = 42;
ready = true;
// Thread 2
while (!ready) { }
System.out.println(value);The answer to this one is not a single output, so the solution shows the fixed program instead.
Show solution
public class VisibilityFixed {
static volatile boolean ready = false;
static int value = 0;
public static void main(String[] args) throws InterruptedException {
Thread reader = new Thread(() -> {
while (!ready) { }
System.out.println(value);
});
reader.start();
value = 42;
ready = true;
reader.join();
}
}42Why this answer?
Without volatile there is no happens-before edge between the threads. Thread 2 may loop forever, because the JIT is allowed to read ready once and keep the value in a register. It may also print 0 or 42. Making ready volatile fixes both problems: the volatile write comes after value = 42, so a thread that reads ready as true must also see 42. Give yourself the point if you named both the endless loop and the volatile fix. Revise: Java Memory Model and Happens-Before.
Puzzle 2: Two Lists, One Class
What is printed?
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
System.out.println(a.getClass() == b.getClass());Show solution
import java.util.ArrayList;
import java.util.List;
public class ErasurePuzzle {
public static void main(String[] args) {
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
System.out.println(a.getClass() == b.getClass());
}
}trueWhy this output?
Type erasure. The type arguments exist only for the compiler; at runtime both objects are plain ArrayList, and there is only one ArrayList class. Revise: Type Erasure in Java.
Puzzle 3: The Key That Changed
What is printed?
record Key(List<String> parts) {}
var parts = new ArrayList<>(List.of("a"));
var map = new HashMap<Key, String>();
map.put(new Key(parts), "value");
parts.add("b");
System.out.println(map.get(new Key(List.of("a"))) + " "
+ map.get(new Key(parts)) + " " + map.size());Show solution
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MutableKeyPuzzle {
record Key(List<String> parts) {}
public static void main(String[] args) {
var parts = new ArrayList<>(List.of("a"));
var map = new HashMap<Key, String>();
map.put(new Key(parts), "value");
parts.add("b");
System.out.println(map.get(new Key(List.of("a"))) + " "
+ map.get(new Key(parts)) + " " + map.size());
}
}null null 1Why this output?
A record is only shallowly immutable: the stored key still points at the same parts list, which now holds [a, b]. The first lookup uses the old hash code and finds the right bucket, but [a] doesn't equal [a, b]. The second lookup has the right contents but a new hash code, which doesn't match the hash the map saved when the entry went in. The entry is still there (the size is 1) but no lookup can reach it. Never change an object while it is a map key. Revise: Object Equality and Hash Codes in Java.
What Your Score Means
| Score (out of 23) | What it means | What to do next |
|---|---|---|
| 20 to 23 | You know Java from the inside | Move on to Core Java Interview Questions and practice explaining these answers out loud |
| 16 to 19 | A pass, with a few gaps | Read the lessons linked from the questions you missed |
| Under 16 | Not yet | Start from JVM Architecture Overview, work through the memory model and concurrency lessons, and take the test again |
Was this tutorial helpful?