skip to content

JVM

Every JVM language ultimately runs here, so senior interviews drift away from syntax and toward the runtime underneath: how bytecode is interpreted and then JIT-compiled, where memory actually lives, how the collector reclaims it, and how classes are found and linked. This is the language-neutral half of a Java, Kotlin, or Scala interview.

on this pageshow

explore

questions

185 · 7 sections

What is the bytecode that a Java compiler emits into .class files, and why does the JVM execute that form instead of executing source text directly or compiling straight to native machine code?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Bytecode is a compact, platform-neutral instruction set for an abstract machine, stored in .class files. The compiler targets that abstract machine instead of a real CPU, so one compiled artifact runs on any JVM, and the JVM can verify it before running it.

open as a page

Compiling a Java application ahead of time into a standalone native executable is an alternative to running it on the JVM with just-in-time compilation. What do you gain and what do you give up?

level: middleimportance: must knowfreq 45%
basics
~20 s

You gain millisecond startup, immediate peak-ish performance, and a much smaller memory footprint with no compiler or class loading at runtime. You give up profile-guided peak throughput, runtime dynamism such as unconstrained reflection, and fast builds.

open as a page

Trace, in order, what a Java Virtual Machine does from the moment running code first references a type until that type's methods are executing as JIT-compiled native code — and name which JVM subsystem owns each step.

level: middleimportance: must knowfreq 52%
basics
~20 s

Order: load, verify, prepare, resolve, initialize, interpret, profile, compile. The class loader subsystem owns the first five (loading through running the static initializer); the execution engine owns the last three (interpreting bytecode, gathering profile counters, and JIT-compiling hot methods into native code).

open as a page

Describe the three top-level subsystems that make up a Java Virtual Machine implementation and what each one is responsible for.

level: middleimportance: must knowfreq 62%
basics
~20 s

Class loader subsystem: finds class files and loads, links (verify, prepare, resolve) and initializes types. Runtime data areas: heap, per-thread stacks and program counters, class-metadata area, code cache. Execution engine: interpreter, JIT compiler and garbage collector, which actually run and maintain the code.

open as a page

Interpreting bytecode instruction by instruction is portable but slow. Mechanically, where does the slowness come from, and why does a runtime that interprets first still keep an interpreter around after it can compile code to native instructions?

level: middleimportance: must knowfreq 55%
basics
~20 s

Each bytecode costs decode plus an indirect dispatch on top of its actual work, values shuttle through the operand stack instead of registers, and nothing is optimized across instruction boundaries. The interpreter is kept because it starts instantly, costs no compile time for cold code, and is the fallback when compiled code must be abandoned.

open as a page

Trace what happens to a newly allocated Java object that stays reachable across several young-generation collections: where does it physically live at each step, what copies it, and what eventually moves it into the old generation?

level: juniorimportance: must knowfreq 62%
basics
~20 s

It is allocated in eden. Each young collection copies the still-live object into the currently empty survivor space and increments its age. After surviving enough collections (age reaching the tenuring threshold) it is copied into the old generation instead — that copy is called promotion.

open as a page

In a HotSpot JVM with a generational heap, what are eden, the survivor spaces and the old generation, and what does each one hold?

level: juniorimportance: must knowfreq 58%
basics
~20 s

The heap is shared by all threads and split into a young generation and an old generation. Young holds eden, where new objects are created, plus two survivor spaces holding objects that survived recent collections. Old holds objects that survived long enough to be promoted.

open as a page

In the HotSpot JVM, what data is stored in the metaspace region, and why does the JVM keep that data in native memory rather than inside the Java heap?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Metaspace holds per-class runtime metadata: type structures, method bytecode, runtime constant pools, field and method descriptors, dispatch tables. It lives in native OS memory, so it grows on demand instead of competing for a fixed slice of the heap.

open as a page

In the JVM, what is a thread stack, and what is pushed onto it while a method executes?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Every JVM thread gets its own stack, created with the thread. Each method invocation pushes one frame holding that call's local variables and working values; returning pops it. Stacks are private to their thread and disappear when the thread ends.

open as a page

What is a thread-local allocation buffer (TLAB) in the HotSpot JVM, and why does having one make object allocation cheap?

level: middleimportance: must knowfreq 60%
basics
~20 s

A TLAB is a private chunk of the young space handed to one thread. Inside it the thread allocates by advancing a pointer, with no lock and no atomic instruction. Only buffer refills and oversized objects touch the shared heap.

open as a page

Describe how a mark-sweep garbage collection algorithm works, phase by phase, and explain the characteristic problem it leaves behind in the heap.

level: juniorimportance: must knowfreq 68%
basics
~20 s

Mark: trace from the roots and flag every reachable object. Sweep: walk the heap and return every unflagged object's space to a free list. Nothing moves, so surviving objects stay put and the reclaimed gaps between them leave the heap fragmented.

open as a page

What is the Serial garbage collector in the HotSpot JVM, how does it collect the young and the old generation, and how do you turn it on?

level: juniorimportance: must knowfreq 52%
basics
~20 s

HotSpot's simplest collector: one GC thread, and every collection stops all application threads. The young generation is collected by copying live objects into a survivor space; the old generation by a mark-compact pass. Enable it with -XX:+UseSerialGC.

open as a page

What does a 'stop-the-world' pause mean inside a JVM, and why does a garbage collector need application threads suspended at all?

level: juniorimportance: must knowfreq 58%
basics
~20 s

A stop-the-world pause is an interval where the JVM suspends every application thread so the runtime can do work that needs a stable view of the heap and of thread state — for example scanning thread stacks for references. Application code makes no progress for the duration.

open as a page

Concurrent garbage collectors describe objects as white, gray, or black while tracing. Define each colour, and explain what the collector has established once no gray objects remain.

level: middleimportance: must knowfreq 52%
basics
~20 s

White means not yet reached, gray means reached but its outgoing references not yet scanned, black means reached and fully scanned. When no gray objects remain, tracing is complete: everything reachable is black and every remaining white object is unreachable and can be reclaimed.

open as a page

The Garbage-First collector is named for the order in which it reclaims memory. Explain what 'garbage first' means in practice and how the collector chooses which heap regions go into the next collection set.

level: middleimportance: must knowfreq 55%
basics
~20 s

G1 tracks how much live data each region holds. For a given pause it collects all young regions plus, in mixed collections, the old regions with the least live data - the most garbage - because evacuation cost scales with live bytes, so those regions give the most free space per millisecond spent.

open as a page

Which class loaders does a modern JVM create at startup, what does each of them load, and how are they linked to one another?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Three built-in loaders: the bootstrap loader (native, no parent) defines the core runtime classes; the platform loader defines the remaining JDK modules; the application (system) loader defines your code from the class path and module path. They form a chain: application -> platform -> bootstrap.

open as a page

When running code references a class for the first time, the JVM has to load it. Concretely, what happens during that loading step — where do the class's bytes come from, and what does the JVM end up with in memory?

level: juniorimportance: must knowfreq 60%
basics
~20 s

A class loader is asked for a binary name and produces the class's bytes (usually a .class file on the classpath, but any source works). The JVM parses that byte stream, loads the superclass and superinterfaces first, and creates a runtime type: internal class metadata plus a java.lang.Class object on the heap.

open as a page

Walk through, step by step, what a standard Java class loader does when it is asked to load a type it has not loaded before. Which loader ends up actually defining a core JDK type such as java.util.List?

level: juniorimportance: must knowfreq 60%
basics
~20 s

It first checks whether it has already loaded that name; if not, it asks its parent, which asks its own parent, all the way up to the bootstrap loader. Only if every ancestor fails does it try to find the bytes itself. Core JDK types are therefore always defined by the bootstrap loader.

open as a page

Inside one running JVM, is a fully-qualified name such as com.acme.Config enough to identify a type uniquely? Explain what actually determines a class's runtime identity.

level: middleimportance: must knowfreq 45%
basics
~20 s

No. A runtime type is identified by the pair (fully-qualified name, defining class loader). Load the same class file with two different loaders and you get two distinct, non-interchangeable types, each with its own Class object.

open as a page

How would you implement a class loader that loads class bytes from a non-standard source such as a database row or an encrypted archive, and which methods of java.lang.ClassLoader do you override?

level: middleimportance: must knowfreq 45%
basics
~20 s

Extend java.lang.ClassLoader, override findClass(name): fetch the bytes yourself, then call the protected defineClass(name, bytes, 0, len), which asks the VM to parse them into a runtime Class. Leave loadClass alone so parent delegation still works.

open as a page

Java is often described as both compiled and interpreted. After a class is loaded, what actually executes its methods, and how does that change while the program keeps running?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Source is compiled ahead of time into bytecode. At runtime the JVM first interprets that bytecode, counts how often each method runs, and once a method is hot a just-in-time compiler turns it into native machine code used from then on. Both modes run side by side.

open as a page

A Java service handles the same kind of request over and over. The first few hundred requests are visibly slower than requests handled a minute later, with no change to code, data or load. What is the JVM doing under the hood, and how does it decide which code deserves the speed-up?

level: juniorimportance: must knowfreq 52%
basics
~20 s

The JVM first interprets bytecode while counting execution. Each method has counters for how often it is called and how often its loops iterate; when a counter crosses a threshold the JVM compiles that method to optimized native code, so hot paths speed up after warm-up.

open as a page

HotSpot ships two just-in-time compilers, historically called the client (C1) and server (C2) compilers. How do they differ in design goals and output, and why does a single JVM contain both?

level: middleimportance: must knowfreq 58%
basics
~20 s

C1 compiles fast and optimizes lightly, so code becomes native quickly with modest peak speed. C2 optimizes aggressively and compiles slowly, giving the best steady-state throughput. A single JVM uses both: C1 for quick warmup and profiling, C2 for the hottest methods.

open as a page

What does it mean for a JIT compiler to compile a method speculatively, and what does the JVM do at runtime when one of those speculative assumptions turns out to be wrong?

level: middleimportance: must knowfreq 50%
basics
~20 s

The JIT compiles using the profile gathered so far — e.g. only one receiver type seen, this branch never taken — and replaces the unproven path with an uncommon trap. If the assumption breaks, the trap fires, the runtime deoptimizes that frame back to the interpreter at the same bytecode, and the method is later recompiled without the failed assumption.

open as a page

HotSpot decides which bytecode to compile using two per-method counters. Name them, explain why one is not enough, and describe what the runtime does when a counter crosses its threshold.

level: middleimportance: must knowfreq 45%
basics
~20 s

An invocation counter (incremented on method entry) and a back-edge counter (incremented on every backward branch, i.e. loop iteration). Invocations alone miss long-running loops in rarely called methods. Crossing a threshold files an asynchronous compilation request; back-edge overflow requests on-stack replacement.

open as a page

Which individual field and array-element reads and writes does the Java Language Specification guarantee to be atomic, and which ones does it explicitly leave non-atomic?

level: middleimportance: must knowfreq 50%
basics
~20 s

Reads and writes are atomic for object references and for every primitive type except long and double. Non-volatile long and double accesses may be split into two 32-bit halves, so a reader can see a mix of two values. Declaring them volatile makes them atomic again.

open as a page

In the Java Memory Model, what special visibility guarantee applies to an instance field declared `final`, and what must the reading thread do to obtain it?

level: middleimportance: must knowfreq 55%
basics
~20 s

Final fields are frozen when the constructor returns. Any thread that later obtains the object's reference sees those fields correctly initialized, with no lock and no volatile on the reader's side, provided the reference did not escape during construction.

open as a page

Which specific rules does the Java Language Specification list as creating a happens-before edge between two actions? Enumerate them.

level: middleimportance: must knowfreq 65%
basics
~20 s

Program order within a thread; unlocking a monitor before any later lock of it; a volatile write before any later read of that field; Thread.start before the new thread's actions; a thread's actions before a successful join; interrupt before the interrupt is detected; constructor end before the finalizer; default writes before any thread starts; plus transitivity.

open as a page

In Java, the `volatile` keyword, `synchronized` blocks, `final` fields, and the `java.util.concurrent.atomic` classes (or `VarHandle` access modes) each grant a *different subset* of the guarantees the Java Memory Model specifies. For each of those four constructs, state precisely what the specification grants and what it withholds, and give a concrete bug that follows from picking the wrong one.

level: middleimportance: must knowfreq 62%
basics
~20 s

volatile: visibility and ordering for that field plus single read/write atomicity, but no compound atomicity. synchronized: all three, only for threads taking the same lock. final: a one-time publication freeze at constructor end, nothing else. Atomics/VarHandle: single-variable atomicity, never multi-variable.

open as a page

Why does the Java Language Specification define a memory model at all? What would be left unspecified about a multi-threaded Java program if it did not?

level: middleimportance: must knowfreq 55%
basics
~20 s

Because compilers and CPUs freely transform code, the language must state which value a read of a shared field may legally return. The memory model is that contract: it bounds optimization and reordering so one program behaves the same on every CPU.

open as a page

A HotSpot JVM prints this garbage-collection log line: `[3.216s][info][gc] GC(7) Pause Young (Normal) (G1 Evacuation Pause) 512M->96M(1024M) 14.221ms`. Walk through what each field on that line means.

level: juniorimportance: must knowfreq 55%
basics
~20 s

[3.216s] is uptime, info the log level, gc the tag, GC(7) the collection's id. It was a young pause caused by G1 evacuation. Heap used went 512M before to 96M after, of 1024M total, taking 14.221 ms stop-the-world.

open as a page

Which garbage collector does a modern HotSpot JVM use if you specify nothing, and what makes it pick a different one on its own?

level: juniorimportance: must knowfreq 55%
basics
~20 s

On JDK 9 and later the default is G1 on any server-class machine (roughly two or more CPUs and enough memory). On a smaller machine or container, JVM ergonomics falls back to Serial. On JDK 8 the default was the Parallel collector.

open as a page

What do the Java command-line options -Xms and -Xmx set, and what does the HotSpot JVM choose for them when you specify neither?

level: juniorimportance: must knowfreq 55%
basics
~20 s

-Xms is the initial heap size the JVM commits at startup; -Xmx is the maximum it may grow to. With neither set, HotSpot defaults to roughly 1/64 of available memory for initial and 1/4 for maximum, reading the container limit rather than host RAM when running under one.

open as a page

How do you enable garbage-collection logging on a HotSpot JVM running JDK 9 or later, and which options control the log destination, the level of detail, and file rotation?

level: middleimportance: must knowfreq 60%
basics
~10 s

Use the unified logging flag -Xlog. Its four colon-separated parts are selectors, output, decorators, output options: -Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=10,filesize=20M. It replaced -XX:+PrintGCDetails and -Xloggc, and is cheap enough to leave on in production.

open as a page

Reading a HotSpot garbage-collection log, how do you tell a young (minor) collection from a mixed collection and from a full collection, and why is spotting a full collection important?

level: middleimportance: must knowfreq 58%
basics
~20 s

Young collections log Pause Young, G1's mixed ones Pause Young (Mixed) (young plus some old regions), and full ones Pause Full, which collects and compacts the whole heap in one long stop. Under G1 or a concurrent collector, a Full GC signals the concurrent machinery failed to keep up.

open as a page