The can't-skip Java interview checklist
The master list of 73 Java interview must-says across 14 areas, each with the exact fact an interviewer is waiting for and links to its revision sheet and full lesson, prioritised by how often it's asked.
On this page
- Priority at a glance
- 1. Core Java and OOP
- 2. Strings
- 3. equals and hashCode
- 4. Exceptions (can't-miss)
- 5. Collections and HashMap
- 6. Generics
- 7. Concurrency basics (can't-miss)
- 8. The Java memory model (can't-miss)
- 9. Locks, atomics, executors and CompletableFuture
- 10. Concurrent collections
- 11. JVM memory, class loading and GC
- 12. Java 8 to 21 features
- 13. Design patterns and SOLID
- 14. Production and debugging
- How to say it in the interview
✅ What is the can't-skip checklist?
It's the list I'd hand a friend who has a Java interview in two weeks: 73 items, grouped into 14 areas, each with the exact sentence the interviewer is waiting to hear. Every item links to its Last-Mile revision sheet for the why, and to the full lesson for the depth. Think of it as a pilot's pre-flight checklist: experienced pilots still run it, because the cost of missing one line is far higher than the 10 minutes it takes.
For this lesson, we'll go area by area through every item that comes up again and again in Java interviews, ordered roughly by how often it's asked. I've written each must-say as the fact itself, not a topic name, because "know HashMap" is useless as a checklist item and "load factor 0.75, resize doubles, treeify at 8 when the table is 64+" is something you can test. Three areas carry a can't-miss flag: exception handling, the Java memory model and multithreading. Those are where I've seen the most otherwise strong candidates lose an offer.
Below the line (out of scope)
- How to schedule these 73 items over 15 or 30 days: How to use Last-Mile Java
- The why behind each item, with code: the eight revision sheets linked in the table below
- Spring, Hibernate, I/O and NIO internals: see Module 07: I/O and NIO and the Interview Arsenal
The 30-second answer
If you can say every item on this page out loud in under 60 seconds each, you're covered for the Java part of almost any interview loop. The heaviest areas are concurrency (threads, synchronized, volatile, happens-before, thread pools, ConcurrentHashMap) and collections (HashMap internals, equals/hashCode), followed by exceptions, core OOP, the JVM and GC, Java 8 to 21 features, and design patterns. Tick an item only when you've said it cleanly without notes, re-test it 2 and 6 days later, and spend your last week on whatever is still unticked rather than re-reading what you know.
What you’ll learn
- See every can't-skip Java interview topic in one place, grouped into 14 areas
- Know the exact must-say fact for each item, not only its name
- Prioritise by how often each area is asked, with concurrency, the JMM and exceptions first
- Spot the two classic bugs on sight: double-checked locking without volatile and the mutable HashMap key
- Use the list as a last-week self-test that links straight to the right revision sheet and full lesson
Interview radar
Asked very often: HashMap internals, equals and hashCode, checked versus unchecked exceptions, synchronized versus volatile, ThreadPoolExecutor parameters, streams and Optional.
Senior rounds probe: happens-before and safe publication, ConcurrentHashMap internals, CompletableFuture composition, virtual threads and pinning, G1 versus ZGC, how you'd find a memory leak.
Production angle: swallowed exceptions, unbounded executor queues, mutable map keys, and reading a thread dump during an incident.
01Priority at a glance
Not every area deserves the same time. The table below is the ranking I'd use, with the days each area gets in the 30-day plan and the 15-day sprint. If you're short on time, work top to bottom and stop where the clock stops.
| Area | How often asked | Days (30 / 15) | Revision sheet |
|---|---|---|---|
| Multithreading, JMM, locks, executors, concurrent collections | Very high, deepest probes | 7 / 4 | Multithreading and the JMM |
Collections, HashMap, generics |
Very high | 5 / 2 | Collections and HashMap |
| Exceptions | High, every level | 2 / 1 | Exceptions |
Core Java, OOP, strings, equals/hashCode |
High, usually the opener | 2 / 1 | Core Java and OOP |
| Java 8 to 21 | High for streams, medium for 17 to 21 | 2 / 1 | Java 8 to 21 |
| JVM memory, GC, production debugging | Medium; very high for senior | 3 / 1 | JVM memory and GC |
| Design patterns and SOLID | Medium, often inside coding | 2 / 1 | Design patterns and SOLID |
| Everything, rapid-fire | Your last two days | 2 / 2 | The final 48 hours |
The table hides one thing: how the mix shifts with seniority. The heat map below shows how often each area comes up by round type. Notice how the senior column turns red for concurrency, the JMM, the JVM and debugging, and the production column for the JVM and debugging, while the phone-screen column is dominated by core Java, equals/hashCode, exceptions and collections.
A heat map with 14 Java areas as rows and four interview types as columns: phone screen, mid-level loop, senior loop and production round; core Java, equals and hashCode, exceptions and collections are almost always asked from the phone screen onward, while the memory model, executors, JVM and production debugging become almost always asked only in senior and production rounds
Each item below has two links. Revise opens the Last-Mile sheet with the must-say and the why. Full lesson opens the deep lesson where it's published, or the module overview where it's still being written. Open the full lesson only when the sheet isn't enough.
021. Core Java and OOP
Priority: high, and almost always the first 10 minutes. These are quick to fix and expensive to fumble, because a shaky answer here colours how the interviewer hears everything after.
- Pass-by-value: Java always passes by value; for objects, the value copied is the reference, so a method can mutate the object but reassigning the parameter never changes the caller's variable. Revise · Full lesson
- Overloading vs overriding: overloading is chosen at compile time from the static argument types; overriding is chosen at runtime from the object's actual class.
static,privateandfinalmethods are not overridden; astaticmethod with the same signature hides the parent's. Revise · Full lesson - Abstract class vs interface: an abstract class can hold instance state and constructors but you extend only one; an interface has no instance state, a class implements many, and since Java 8 and 9 it can have
default,staticandprivatemethods. Interface for a capability, abstract class for a shared skeleton with state. Revise · Full lesson staticandfinal:staticmeans one copy per class (per class loader), not per object;finalon a variable means assigned once (the referenced object can still change), on a method means no override, on a class means no subclass. Revise · Full lesson- Immutable class recipe:
finalclass,private finalfields, no setters, defensive copies of mutable inputs and outputs, and don't leakthisfrom the constructor. You get thread safety and safe hash keys for free. Revise · Full lesson - Composition over inheritance: inheritance couples you to the parent's implementation, so a parent change can break subclasses (the fragile base class problem). Use
extendsonly for a true is-a that respects substitution; otherwise hold the object and delegate. Revise · Full lesson - Autoboxing and the Integer cache:
Integer.valueOfcaches -128 to 127, so==on two boxed127s istrueand on two128s isfalse; always compare boxed values withequals. Unboxing anullthrowsNullPointerException. Revise · Full lesson
032. Strings
Priority: high on phone screens. Interviewers use strings to check whether you understand references, immutability and memory in one small topic.
- Why
Stringis immutable: so strings can be shared safely in the pool, cache theirhashCode, be used as map keys, be shared across threads without locks, and not be changed after a security check (file paths, class names, URLs). Revise · Full lesson - String pool and
==: literals are interned in the string pool, which lives on the heap since Java 7;new String("a")always creates a new object, so==compares references andequalscompares characters. Revise · Full lesson StringBuildervsStringBuffer: concatenating in a loop copies the whole string each time (O(n²) characters); useStringBuilder, which is unsynchronized.StringBuffersynchronizes every method and is legacy. Since Java 9, a singlea + b + ccompiles toinvokedynamic, but loops still need a builder. Revise · Full lesson- Compact strings: since Java 9, a
Stringis backed by abyte[]plus a coder flag, using 1 byte per character for Latin-1 text and 2 for anything else, which roughly halves string memory in ASCII-heavy heaps. Revise · Full lesson
043. equals and hashCode
Priority: very high. This is the bridge between core Java and collections, and it's the topic I'd bet on appearing in any Java loop.
- The contract:
equalsmust be reflexive, symmetric, transitive, consistent and returnfalsefornull; equal objects must have equal hash codes, while unequal objects may collide. Revise · Full lesson - Override both or neither: override
equalswithouthashCodeand two equal keys land in different buckets, soHashMap.getmisses and aHashSetholds "duplicates". Use the same fields in both. Revise · Full lesson - Mutable keys get lost: change a field used by
hashCodeafter inserting the key and the entry stays in the old bucket, sogetandremovecan't find it (see the snippet below). Revise · Full lesson - Records and
compareToconsistency: records generateequals,hashCodeandtoStringfrom their components. Sorted collections usecompareTo, notequals:new BigDecimal("1.0")andnew BigDecimal("1.00")are two elements in aHashSetbut one in aTreeSet. Revise · Full lesson
Here's the mutable-key bug in five lines. Before reading the comment, predict what the last line prints.
List<String> key = new ArrayList<>(List.of("a"));
Map<List<String>, Integer> map = new HashMap<>();
map.put(key, 1);
key.add("b"); // hashCode of the key changes
System.out.println(map.get(key)); // null: lookup goes to a different bucket
054. Exceptions (can't-miss)
Priority: high at every level, and a favourite for judging production maturity. Exception questions start easy ("checked vs unchecked?") and turn senior fast ("where do you catch, where do you log, what happens to the interrupt flag?").
Exception handling is asked in almost every Java loop, from phone screen to senior. Get all 8 items below to green before you move on.
- The hierarchy:
Throwablesplits intoError(OutOfMemoryError,StackOverflowError; don't catch these) andException;RuntimeExceptionand its subclasses are unchecked, every otherExceptionis checked and must be caught or declared. Revise · Full lesson - Checked vs unchecked, with an opinion: checked for recoverable conditions the caller can act on (
IOException), unchecked for programming errors (IllegalArgumentException,NullPointerException). Most modern code and frameworks prefer unchecked, partly because checked exceptions don't fit lambdas. Revise · Full lesson finallysemantics:finallyruns aftertryorcatch, even after areturn; it doesn't run if the JVM exits (System.exit, crash, kill). Areturninsidefinallyoverrides the earlier result and silently swallows any exception. Revise · Full lesson- try-with-resources: works with any
AutoCloseable(Java 7+), closes resources in reverse declaration order, and if both the body andclose()throw, the body's exception propagates with the close failure attached viagetSuppressed(). Revise · Full lesson - Custom exceptions and chaining: name exceptions after the failure (
PaymentDeclinedException), extendRuntimeExceptionunless callers must recover, and always pass the cause (new X(msg, cause)) so the original stack trace survives. Revise · Full lesson - Handling in production: never swallow with an empty
catch; log once at the boundary instead of log-and-rethrow at every layer; translate low-level exceptions at layer boundaries; don't catchThrowablebroadly. Revise · Full lesson InterruptedException: catching it clears the thread's interrupt flag, so either rethrow it or callThread.currentThread().interrupt()to restore it; swallowing it makes threads impossible to cancel and pools impossible to shut down. Revise · Full lesson- Cost and overriding rules: creating an exception is expensive mainly because
fillInStackTracewalks the stack, so never use exceptions for normal control flow. An overriding method may not throw new or broader checked exceptions than the method it overrides. Revise · Full lesson
065. Collections and HashMap
Priority: very high. "How does HashMap work?" is the single most common Java internals question, and the follow-ups go straight into concurrency.
ArrayListvsLinkedList:ArrayListgives O(1) random access and amortised O(1) append, growing by 1.5x;LinkedListis O(n) forget(i), costs an extra node object per element and has poor cache locality.LinkedListrarely wins; useArrayDequefor queues and stacks. Revise · Full lessonHashMapput and get: spread the hash withh ^ (h >>> 16), pick the bucket with(n - 1) & hash, then match by stored hash,==, thenequals. Default capacity 16 and load factor 0.75, so the first resize happens at 13 entries and doubles the table. Revise · Full lesson- Treeification: since Java 8, a bucket turns into a red-black tree once it holds 8 nodes and the table has at least 64 buckets (below 64 it resizes instead), and turns back into a list at 6. Worst-case lookup drops from O(n) to O(log n). Revise · Full lesson
- Ordering:
HashMap,LinkedHashMap,TreeMap:HashMaphas no order and allows onenullkey;LinkedHashMapkeeps insertion or access order (access order plusremoveEldestEntrygives an LRU cache);TreeMapis a sorted red-black tree with O(log n) operations that usescompareTo. Revise · Full lesson - Fail-fast iterators: iterators check a
modCountand throwConcurrentModificationExceptionon structural changes during iteration, even in one thread; it's best-effort, not a guarantee. Remove withIterator.remove()orremoveIf. Revise · Full lesson HashMapis not thread-safe: concurrentputs can lose entries or corrupt the table; in Java 7, head insertion during resize could form a cycle and hanggetin an infinite loop. Java 8 switched to tail insertion but is still unsafe: useConcurrentHashMap. Revise · Full lesson- Unmodifiable collections:
List.ofandMap.of(Java 9+) are truly unmodifiable and rejectnull;Collections.unmodifiableListis a read-only view whose backing list can still change;Arrays.asListis fixed-size but writable throughset. Revise · Full lesson
076. Generics
Priority: medium. Usually two or three questions, often as a follow-up to collections, and a good place to show you understand compile time versus runtime.
- Type erasure: generic types exist only at compile time; at runtime
List<String>andList<Integer>are the sameListclass, so you can't writenew T(),instanceof List<String>ornew T[10]. Revise · Full lesson - Invariance and PECS:
List<String>is not aList<Object>. Use? extends Twhen you only read from a structure (producer) and? super Twhen you only write to it (consumer): Producer Extends, Consumer Super. Revise · Full lesson - Arrays vs generics: arrays are covariant and reified, so
Object[] a = new String[1]; a[0] = 1;compiles and throwsArrayStoreExceptionat runtime; generics are invariant and catch the same mistake at compile time. Revise · Full lesson
087. Concurrency basics (can't-miss)
Priority: very high. This is where interviewers separate "I've used threads" from "I understand threads", and it's the area with the most follow-up depth.
Multithreading is the most heavily weighted area in the whole plan. Sections 7 to 10 together are 20 items; aim to have all of them green by mock interview 2.
- Creating threads,
startvsrun:Runnablereturns nothing;Callablereturns a value and can throw checked exceptions.start()creates a new thread that callsrun(); callingrun()directly runs on the current thread. In real code, submit tasks to an executor instead ofnew Thread. Revise · Full lesson - Thread states:
NEW,RUNNABLE,BLOCKED(waiting to enter a monitor),WAITING,TIMED_WAITING,TERMINATED. A thread blocked on socket I/O shows asRUNNABLE, which surprises people reading thread dumps. Revise · Full lesson synchronized: acquires the monitor of the object (or of theClassforstaticmethods), gives mutual exclusion and visibility (unlock happens-before the next lock of the same monitor), and is reentrant. Revise · Full lessonwait,notify,sleep:waitandnotifyrequire holding the monitor (elseIllegalMonitorStateException);waitreleases the lock,sleepdoesn't. Always callwaitinside awhileloop that rechecks the condition, because of spurious wakeups, and prefernotifyAll. Revise · Full lesson- Race conditions:
count++is three steps (read, add, write), and check-then-act (if (!map.containsKey(k)) map.put(k, v)) is two; both lose updates under contention. Fix with a lock, an atomic operation (AtomicInteger,computeIfAbsent) or by not sharing the state. Revise · Full lesson - Deadlock: needs all four conditions: mutual exclusion, hold and wait, no preemption, circular wait. Prevent it with a global lock ordering or
tryLockwith a timeout; find it withjstack, which prints "Found one Java-level deadlock". Revise · Full lesson
098. The Java memory model (can't-miss)
Priority: high for mid-level, very high for senior. Few candidates can explain it cleanly, which is exactly why it's such a strong signal when you can.
When I ask "why does this need volatile?", I want happens-before in the first sentence. Practise the five items below until that's automatic.
- What the JMM is: the rules in JLS chapter 17 for when a write in one thread is guaranteed visible to a read in another. Without a happens-before edge, the compiler and CPU may reorder or cache, and a thread can see a stale value forever. Revise · Full lesson
- Happens-before rules: program order within a thread; unlock of a monitor before a later lock of the same monitor; a
volatilewrite before a later read of the same variable;Thread.start()before the started thread's actions; a thread's actions before another thread'sjoin()returns. The relation is transitive. Revise · Full lesson volatile: guarantees visibility and ordering, not atomicity. Good for a stop flag or publishing a fully built object;count++on avolatilefield still loses updates. Revise · Full lesson- Double-checked locking: the field must be
volatile, becauseinstance = new X()is allocate, construct, assign, and withoutvolatilethe assignment can become visible before construction finishes, so another thread sees a half-built object. Simpler alternatives: the holder idiom or anenum. Revise · Full lesson finalfields and safe publication:finalfields are guaranteed visible once the constructor completes, providedthisdidn't escape during construction. Publish shared objects safely through a static initializer, avolatileorfinalfield, a lock, or a concurrent collection. Revise · Full lesson
This is the version of double-checked locking I'd expect you to write on a whiteboard without hesitation:
public final class Config {
private static volatile Config instance; // volatile is the whole point
public static Config get() {
Config local = instance; // one volatile read on the fast path
if (local == null) {
synchronized (Config.class) {
local = instance;
if (local == null) {
instance = local = new Config();
}
}
}
return local;
}
}
109. Locks, atomics, executors and CompletableFuture
Priority: very high for mid-level and senior. Executors are where interviewers check whether you've run concurrent code in production, not only read about it.
ReentrantLockvssynchronized:ReentrantLockaddstryLockwith a timeout,lockInterruptibly, optional fairness and multipleConditions, but you mustunlock()infinally.ReadWriteLockallows many readers or one writer. Default tosynchronizedunless you need one of those features. Revise · Full lesson- Atomics and CAS:
AtomicIntegeruses a compare-and-set retry loop instead of a lock. Watch for the ABA problem (AtomicStampedReferencefixes it), and useLongAdderfor hot counters, since it spreads updates across cells and sums on read. Revise · Full lesson ThreadPoolExecutortask flow: belowcorePoolSizea new thread is created; otherwise the task is queued; if the queue is full, threads are added up tomaximumPoolSize; beyond that theRejectedExecutionHandlerruns (defaultAbortPolicythrows,CallerRunsPolicygives back-pressure). Revise · Full lessonExecutorsfactory traps and sizing:newFixedThreadPooluses an unboundedLinkedBlockingQueue, so a backlog grows untilOutOfMemoryError;newCachedThreadPoolhas no thread limit. Prefer an explicit pool with a bounded queue, sized near the core count for CPU-bound work and cores × (1 + wait/compute) for I/O-bound work. Revise · Full lessonCompletableFuture:supplyAsyncwithout an executor runs onForkJoinPool.commonPool()(cores minus 1 threads), so pass your own executor for blocking I/O.thenApplymaps a value,thenComposechains a call that returns another future,thenCombinejoins two; handle failures withexceptionallyorhandle. Revise · Full lesson- Virtual threads (Java 21): JVM-managed threads mounted on a small pool of carrier threads, so blocking I/O unmounts them instead of holding an OS thread; millions are feasible versus a few thousand platform threads. Don't pool them (limit with a
Semaphore), they don't speed up CPU-bound work, and in Java 21 blocking insidesynchronizedpins the carrier. Revise · Full lesson
1110. Concurrent collections
Priority: high for senior. ConcurrentHashMap in particular is the natural follow-up to every HashMap question.
ConcurrentHashMap: since Java 8 there are no segments; an empty bin is filled with a CAS and a non-empty bin is locked withsynchronizedon its first node, while reads take no lock. It rejectsnullkeys and values (sogetreturningnullalways means absent), offers atomiccompute,mergeandputIfAbsent, and has weakly consistent iterators that never throwConcurrentModificationException. Revise · Full lessonCopyOnWriteArrayListvs synchronized wrappers: copy-on-write copies the whole array on every write, which suits read-mostly lists such as listeners and is terrible for write-heavy ones.Collections.synchronizedMapuses one lock for everything, and you must synchronize manually while iterating. Revise · Full lessonBlockingQueue:putblocks when full andtakeblocks when empty, which gives you producer-consumer for free.ArrayBlockingQueueis bounded with one lock;LinkedBlockingQueueis optionally bounded (default capacityInteger.MAX_VALUE) with separate put and take locks. Revise · Full lesson
1211. JVM memory, class loading and GC
Priority: medium for juniors, very high for seniors. Expect "what's on the heap versus the stack?" at any level and "how would you tune or choose a GC?" at senior level.
- Memory areas: the heap holds objects and is shared and garbage-collected; each thread has its own stack of frames (
-Xss, 1 MB by default on 64-bit Linux); class metadata lives in Metaspace in native memory, which replaced PermGen in Java 8; plus the PC register, native stacks and the code cache. Revise · Full lesson - Which error means what:
Java heap space(too many live objects or a leak),Metaspace(class loader leak),GC overhead limit exceeded(over 98% of time in GC recovering under 2% of heap),unable to create native thread(OS thread limit), andStackOverflowError(deep or infinite recursion). Each points to a different fix. Revise · Full lesson - Class loading: bootstrap, then platform (Java 9+, formerly extension), then application loader, with parent-first delegation so nobody can replace
java.lang.String. A class is loaded, linked (verify, prepare, resolve) and initialized; static initialization runs once and is thread-safe, which the holder idiom relies on. Revise · Full lesson - How GC decides what's garbage: anything not reachable from GC roots (thread stacks, static fields, JNI references) is garbage, which is why cycles are collected and Java doesn't use reference counting. Most objects die young, so the heap is generational: young collections are frequent and cheap, old collections are rarer and costlier. Revise · Full lesson
- Choosing a collector: G1 is the default since Java 9, region-based with a 200 ms pause target (
-XX:MaxGCPauseMillis); ZGC keeps pauses under about 1 ms even on very large heaps (generational with-XX:+ZGenerationalin Java 21); Parallel maximises throughput for batch jobs. Start with G1, move to ZGC when tail latency matters. Revise · Full lesson - Memory leaks in Java: a leak is an unintended reference: static collections, caches without eviction, listeners never removed,
ThreadLocalvalues in pooled threads, inner classes holding their outer instance. Know the four reference strengths: strong, soft, weak, phantom. Revise · Full lesson - Heap sizing in containers: the JVM reads container limits (since Java 10) and by default caps the heap at 25% of available memory, which wastes most of a container. Set
-XX:MaxRAMPercentageto around 70 to 75, leaving room for Metaspace, thread stacks and direct buffers. Revise · Full lesson
1312. Java 8 to 21 features
Priority: high for streams and lambdas, which appear in nearly every coding round; medium for 17 to 21 features, which earn you credit for being current.
- Lambdas and functional interfaces: a lambda implements an interface with exactly one abstract method (
Function,Supplier,Consumer,Predicate,BiFunction); captured local variables must be effectively final. Default methods, added in Java 8, let interfaces such asCollectiongainstream()without breaking implementors. Revise · Full lesson - Streams: lazy, single-use pipelines of intermediate operations (
map,filter) that run only when a terminal operation (collect,forEach) is called.mapis one-to-one,flatMapflattens;Collectors.toMapthrowsIllegalStateExceptionon duplicate keys unless you pass a merge function; parallel streams share the common pool, so avoid them for I/O. Revise · Full lesson Optional: a return type for "may be absent", not for fields, parameters or collections.orElse(x)always evaluatesx,orElseGet(supplier)evaluates only when empty; preferorElseThrowto a bareget(). Revise · Full lesson- Records, sealed types, pattern matching: records (Java 16) are immutable data carriers with generated constructor, accessors,
equals,hashCodeandtoString; sealed types (Java 17) restrict subclasses viapermits; pattern matching forswitchand record patterns (Java 21) give exhaustive switches over a sealed hierarchy with nodefault. Revise · Full lesson - Versions and the smaller features: LTS releases are 8, 11, 17, 21 and 25. Know
var(Java 10, locals only), switch expressions (14), text blocks (15) and sequenced collections (21, addinggetFirst,getLastandreversed). Revise · Full lesson
1413. Design patterns and SOLID
Priority: medium. Usually one or two direct questions, plus credit for applying them naturally while you code.
- Singleton, three ways: an
enumsingleton is the safest (serialization and reflection proof); the holder idiom gives lazy, thread-safe creation through class initialization; double-checked locking works only withvolatile. Mention that singletons hurt testability. Revise · Full lesson - Builder and factories: a builder handles many optional parameters and produces an immutable object; static factory methods (
List.of,Integer.valueOf) have names and can cache instances; abstract factory creates families of related objects. Revise · Full lesson - Strategy, observer, decorator, proxy: strategy swaps an algorithm (a
Comparatorlambda is one); observer pushes events to listeners; decorator wraps to add behaviour (BufferedInputStream); proxy stands in front of an object (Spring AOP,java.lang.reflect.Proxy). Revise · Full lesson - SOLID with one example each: Single responsibility (one reason to change), Open/closed (extend without editing), Liskov (a subtype must be usable wherever the parent is: the square and rectangle problem), Interface segregation (small interfaces), Dependency inversion (depend on abstractions, inject through constructors). Revise · Full lesson
1514. Production and debugging
Priority: low for juniors, very high for seniors. A senior candidate who can't describe reading a thread dump or a heap dump raises a flag, however good the theory was.
- Thread dumps: take them with
jcmd <pid> Thread.printorjstack, three dumps 5 to 10 seconds apart. Look for many threadsBLOCKEDon the same lock, the deadlock section, or all pool threads stuck in the same frame. For high CPU, map the hot OS thread id fromtop -Hto the hexnidin the dump. Revise · Full lesson - Heap dumps: run with
-XX:+HeapDumpOnOutOfMemoryErrorin production, or take one withjcmd <pid> GC.heap_dump; open it in a heap analyser and follow the biggest retained sizes in the dominator tree to the reference holding them. Revise · Full lesson - GC logs, JFR and flame graphs: enable
-Xlog:gc*(unified logging since Java 9) to correlate latency spikes with pauses; JDK Flight Recorder records allocation, locks and hot methods at about 1 to 2% overhead; a flame graph shows where CPU time goes. Revise · Full lesson - One story of your own: have a 90-second story of a real incident (a leak, contention or deadlock, a swallowed exception) told as signal, diagnosis, fix, and what you changed afterwards. Interviewers weigh this more than any definition. Revise · Full lesson
Many candidates tick an item because the name looks familiar ("volatile, yes, I know that one"). This is frequently a mistake because the interviewer isn't asking whether you've heard of it; they're waiting for the specific fact in bold above. If you can't say the must-say sentence nearly word for word, it isn't ticked.
16How to say it in the interview
The checklist is most useful in your last week, when there's no time for new material. Here's how I'd use it. Seven days out, run every unticked item and every item you ticked more than a week ago, out loud, 60 seconds each. Five days out, open the revision sheet only for what failed. Two days out, switch to The final 48 hours and stop opening full lessons altogether.
When I ask any question on this list, I'm listening for the must-say fact first, then the why, then where it breaks. Candidates who lead with the fact sound sure of themselves; candidates who build up to it through background sound like they're searching. The bolded facts above are written to be your first sentence.
In the interview
"A HashMap is an array of buckets. On put, it spreads the key's hashCode with h ^ (h >>> 16), picks a bucket with (n - 1) & hash, and stores the entry there, matching existing keys by hash and then equals. The default capacity is 16 with a 0.75 load factor, so it doubles the table after 12 entries, and since Java 8 a bucket with 8 or more entries becomes a red-black tree once the table has 64 buckets. Two things break it in practice: overriding equals without hashCode, and mutating a key after inserting it. And it isn't thread-safe, so under concurrency I'd use ConcurrentHashMap, which CASes empty bins and locks only the bin it's writing to."
On the whiteboard
- 73 items, 14 areas; tick only after 60 s out loud
- Most days: concurrency + JMM (7), collections (5)
- Can't-miss: exceptions, JMM, multithreading
- Lead with the must-say, then why, then the trap
- Last week: re-test unticked → sheet → final 48 h
- Two snippets to write blind: DCL with
volatile, mutable key bug
Interview questions for this topicComing soon
Further reading (8)
- The Java Language Specification, Java SE 21: Chapter 17, Threads and Locks
- HashMap (Java SE 21 API)
- ConcurrentHashMap (Java SE 21 API)
- ThreadPoolExecutor (Java SE 21 API)
- Java SE 21 HotSpot Virtual Machine Garbage Collection Tuning Guide
- JEP 444: Virtual Threads
- Java Concurrency in Practice (Goetz et al.)
- Effective Java, 3rd ed. (Bloch)