Top 60 Java 21 Interview Questions and Answers (Updated for 2025) — Part 1 (Q1–Q30)
Table of Contents
- Core Java 21 Concepts (Q1–Q6)
- Virtual Threads & Concurrency (Q7–Q14)
- Pattern Matching & Records (Q15–Q20)
- String Templates (Q21–Q22)
- Sequenced Collections & APIs (Q23–Q26)
- JVM, GC & Performance (Q27–Q30)
Core Java 21 Concepts
Answer: Java 21 (LTS) brings several notable features and improvements:
- Virtual Threads (Project Loom) — lightweight threads for scalable concurrency.
- Record Patterns & Pattern Matching Enhancements — deconstruct objects in
instanceofandswitch. - String Templates (preview) — safer and more efficient string interpolation.
- Sequenced Collections — consistent APIs for forward/reverse traversal.
- Scoped Values — safer alternative to ThreadLocal for immutable context propagation.
- Various JVM, GC, and performance improvements.
Answer: Virtual threads are JVM-managed user-mode threads that are much lighter than traditional OS (platform) threads. They enable creating millions of threads with low memory overhead and fast creation/teardown, making blocking I/O programming simple and scalable.
// Simple virtual thread
Thread vt = Thread.startVirtualThread(() -> {
System.out.println("Running in a virtual thread: " + Thread.currentThread());
});
vt.join(); // handle InterruptedException in real code
Answer: ScopedValue (or similar API) provides immutable context that can be passed to code executed in a thread scope. Unlike ThreadLocal, they are designed for structured concurrency and virtual threads — safer and clearer for short-lived context propagation (e.g., request id, tenant id).
Answer: Unnamed pattern components let you ignore parts of a deconstructed pattern using an underscore (_), improving readability when some values aren't needed:
if (obj instanceof Person(String _, int age)) {
System.out.println(age);
}
Answer: Sequenced collections define consistent APIs for collections that have an order — like getFirst(), getLast(), and reversed() view methods. They provide a standard way to access both ends and reversed iteration.
Virtual Threads & Concurrency (Project Loom)
Answer: Reactive frameworks avoid blocking to scale with fewer threads. Virtual threads make blocking I/O cheap, so traditional imperative code can scale without rewriting into a reactive style. Still, reactive can remain useful for some streaming and backpressure scenarios.
Answer: Avoid them for CPU-bound workloads where the bottleneck is CPU and not blocking I/O. For tight compute tasks, thread pooling and work-stealing frameworks tuned to CPU cores are better.
Answer: ThreadLocal works with virtual threads but can lead to accidental high memory retention if used carelessly. Scoped values (or context-passing) are preferred because they avoid hidden mutable state across millions of virtual threads.
Answer: Structured concurrency treats multiple concurrent tasks as a single unit of work (scope), simplifying error handling and cancellation. Combined with virtual threads, structured concurrency enables clean, predictable lifecycles for concurrent tasks.
ExecutorService es = Executors.newVirtualThreadPerTaskExecutor();
try {
es.submit(() -> { /* blocking I/O */ });
} finally {
es.shutdown();
}
Answer: Yes — JFR, thread dumps, profilers, and IDEs (recent versions of IntelliJ, JDK tooling) now provide virtual thread visibility. Some tooling enhancements are still maturing.
Answer: Virtual threads are scheduled by the JVM and mapped to carrier platform threads when they perform blocking operations. This reduces pressure on OS thread limits and scheduling overhead.
- Using mutable ThreadLocal state carelessly.
- Assuming context propagation across async callbacks without structured concurrency.
- Neglecting proper resource limits — millions of VTs can overwhelm external systems (DB connections).
Pattern Matching, Records & Related Features
Answer: Records are a compact way to declare immutable data carriers with auto-generated constructors, equals/hashCode, and accessors. Use records for DTOs and simple value objects where immutability and concise syntax help. Example:
public record User(String name, int age) { }
Answer: Record patterns allow you to deconstruct a record in instanceof or switch, extracting fields inline:
Object o = new User("Jane", 30);
if (o instanceof User(String name, int age)) {
System.out.println(name + " - " + age);
}
Answer: Enhanced switch can match types/patterns and bind variables directly inside case labels, enabling more concise branching:
switch (obj) {
case String s -> System.out.println("String: " + s);
case User(String n, int a) -> System.out.println(n + " is " + a);
default -> System.out.println("Other");
}
record Address(String city, String zip) {}
record Person(String name, Address address) {}
Object o = new Person("Sam", new Address("NYC", "10001"));
if (o instanceof Person(String name, Address(String city, _))) {
System.out.println(name + " from " + city);
}
This demonstrates nested deconstruction in one expression.
Answer: Pattern variables are in scope only within the corresponding branch where the pattern succeeds (e.g., the if body or switch arm). They are not visible outside that scope unless explicitly bound by a broader pattern match.
Answer: Unnamed components (using _) signal that a value is intentionally ignored, improving readability and avoiding unused-variable warnings:
if (o instanceof User(String _, int age)) {
System.out.println(age);
}
String Templates (Preview)
Answer: String templates provide a structured, safer, and often more performant way to build strings with embedded expressions, compared to concatenation or String.format. In Java 21 they are a preview feature; syntax and APIs may evolve.
// Example uses preview API; syntax subject to change
import static java.util.FormatProcessor.FMT;
String name = "Asha";
String msg = FMT."Hello, {name}! Today is {java.time.LocalDate.now()}";
System.out.println(msg);
--enable-preview --release 21.Sequenced Collections & APIs
reversed() on a list and what does it return?Answer: reversed() returns a reversed view of a sequenced collection (not a new independent list). Changes to the underlying collection reflect in the reversed view where supported.
List.of() and new ArrayList<>() in Java 21?List.of()— immutable, optimized, concise factory method.new ArrayList<>()— mutable, resizable backing array.
Answer: Sequenced sets/maps provide predictable first/last operations and reversible traversals. They maintain insertion or defined sequence semantics while exposing additional convenience methods.
Answer: Yes — streams preserve encounter order for ordered collections. Reversed views will have reversed encounter order unless explicitly unordered.
JVM Internals, GC & Performance
- Improved G1 and ZGC performance and diagnostics.
- Faster class data sharing and startup.
- Lower thread scheduling overhead for virtual threads.
- Enhanced profiling hooks for observability (JFR improvements).
Answer: Enhanced JFR events, better thread dumps that include virtual threads, and improved JVM metrics enable deeper runtime introspection for production troubleshooting.
- Virtual threads are lightweight but still allocate objects — tune heap and GC accordingly.
- Monitor allocation rates and object retention (leaky ThreadLocal-like patterns are risky).
- Use low-latency collectors (ZGC) for low pause requirements; test under load.
javac --enable-preview --release 21 MyApp.java
java --enable-preview --enable-preview MyApp
// Or configure Maven/Gradle with compiler args and JVM args for preview
Advanced, Spring & Microservices Questions (Q31–Q40)
Answer: Spring Boot 3.2+ adds compatibility for Java 21. Virtual threads simplify blocking controller code and enable simpler concurrency models. However, check third-party library compatibility and update build toolchain (Maven/Gradle) to use --enable-preview only when necessary.
Answer: No special controller code is required; virtual threads can be used at the server layer (Tomcat/Jetty with Loom support or via a thread-per-request executor). Ensure the underlying servlet container or server supports virtual threads or accept tasks on a virtual-thread-based executor.
Answer: Because virtual threads can increase concurrency massively, connection pools must be right-sized and possibly replace blocking DB calls with async drivers or increase pool size carefully. Use circuit breakers and rate limiting to protect downstream systems.
Answer: Structured concurrency groups related tasks, enabling aggregated exception handling and deterministic cancellation. Instead of managing many futures, a parent scope can wait/join children and propagate failures predictably.
Answer: Start with endpoints that are simple blocking I/O, replace reactive handlers with imperative ones, ensure connection pools and downstream systems are tuned, add structured concurrency for grouped work, and run load tests to validate behavior.
Answer: Most libraries work, but pay attention to libraries that assume per-thread context/ThreadLocal lifecycle. Session/transaction management must be tested for virtual-thread safety. Use scoped values or explicit context objects when needed.
Answer: Implement backpressure, semaphore-based throttling, rate limiting, bounded queues, and limit external concurrency (DB, remote APIs). Use observability metrics to detect saturation early.
Answer: Use tools like Gatling or k6 to simulate realistic traffic patterns, monitor CPU, allocation rates, GC pauses, DB connection pool metrics, response latencies, and JFR recordings. Test failover and peak bursts to find bottlenecks.
Answer: Virtual threads appear in thread dumps with special markers. Tools and JFR show virtual-thread stacks and carrier threads. Ensure tooling versions support the JVM version to get accurate diagnostics.
Answer: Treat values interpolated into templates like any user input: escape or validate values before embedding, prefer typed template processors with safe variable handling, and avoid building SQL or HTML directly from templates without sanitization.
JVM, Performance & Low-Level Questions (Q41–Q46)
Answer: Class-data sharing reduces startup time and memory footprint by sharing common class metadata among JVMs. Java 21 improves CDS by expanding supported classes and optimizing startup paths.
Answer: Use JFR for lightweight sampling, collect flame graphs, use async-profiler or YourKit for CPU/memory hotspots, and collect heap/GC logs. Run targeted recordings during suspicious periods and correlate with business metrics.
Answer: ThreadLocal values can leak memory or be unexpectedly shared if not cleared. Since virtual threads are short-lived and numerous, relying on ThreadLocal for long-lived state is risky. Scoped values or explicit passing are safer.
Answer: Choose ZGC for ultra-low pause requirements and large heaps; prefer G1 for general-purpose workloads with moderate heaps. Benchmark under realistic loads — GC behavior depends on application allocation rates and pause-sensitivity.
Answer: Escape analysis determines whether objects can be stack-allocated or optimized away. It reduces heap allocations and GC pressure. Modern JVMs perform aggressive optimizations benefiting high-concurrency apps.
Answer: Use JFR allocation profiling, async-profiler allocation mode, or JVM tools that report bytes/s allocated. Correlate allocation rate with GC activity to find hotspots and optimize by reusing buffers or object pooling where appropriate.
Code Output & Prediction Questions (Q47–Q52)
Thread t = Thread.startVirtualThread(() -> System.out.println("Hi"));
t.join();
Output: Hi — The virtual thread runs the lambda and join() waits for completion.
record Employee(String name, int id) {}
Object o = new Employee("Alice", 101);
if (o instanceof Employee(String name, int _)) {
System.out.println(name);
}
Answer: Yes, it compiles. It prints Alice. The underscore is an unused component; extraction still binds name.
List list = List.of("a", "b", "c");
System.out.println(list.reversed().get(0));
Answer: It prints c because reversed() returns a view with reversed encounter order.
List l = new ArrayList<>();
l.add("x");
l.add("y");
List r = List.copyOf(l).reversed();
System.out.println(r);
Answer: List.copyOf(l) returns an immutable list [x,y]; reversed() returns a view [y,x], so printing [y, x]. Note immutability prevents modifying the original via the view.
var with pattern matching?Answer: var cannot be used where a type pattern is required. Unnamed variables/var-like features are handled differently in pattern contexts; the language defines explicit scoping rules for pattern variables.
Answer: Behavior may be unstable if the preview feature changes in future JDK updates. Code using preview APIs can break when the API evolves — avoid shipping preview-dependent code to production unless you accept maintenance risk or control the JVM version tightly.
Architecture & Systems Questions (Q53–Q56)
Answer: Use virtual-thread-per-request model, bounded queues at ingress, proper connection pool sizing, circuit breakers for downstream calls, structured concurrency for composed tasks, and strong observability (JFR, metrics). Ensure limits on external calls and fallback mechanisms to prevent cascading failures.
Answer: Apply request throttling, rate limits, authentication/authorization checks early, backpressure, and quotas per tenant. Use a gateway to enforce limits and isolate heavy users.
Answer: Limit concurrency to external services via semaphore or bulkhead patterns, use timeouts, and optionally offload to dedicated carrier thread pools to prevent blocking critical carriers.
Answer: Use non-blocking appenders, structured logs (JSON), log sampling for high-throughput endpoints, and include trace/context IDs using scoped values or explicit context objects for correlating requests.
Miscellaneous, Future, and Best Practices (Q57–Q60)
Answer: The JDK team ships features as previews to gather developer feedback and iterate quickly. This accelerates innovation but requires developers to follow releases closely and be ready to adapt preview APIs that may change.
Answer: Isolate preview usage behind feature flags, keep dependencies on stable versions where possible, run extensive tests on upgrade paths, and document the preview usage with migration plans.
- Official JEPs and OpenJDK mailing lists
- Project Loom drafts & documentation
- Java language enhancement proposals (JEPs)
- Blogs and talks by JVM engineers (e.g., Oracle, Azul)
- Hands-on sample projects and load-tests
- Understand virtual threads deeply — lifecycle, scheduling, and pitfalls.
- Practice pattern matching and record deconstruction with examples.
- Know when to use sequenced collections and string templates (preview caveats).
- Be prepared to discuss observability, GC tuning, and production load testing.
- Show awareness of compatibility and migration considerations for Spring and third-party libraries.
๐ Conclusion
These 60 questions cover practical, design, and language-level aspects of Java 21 that are commonly probed in interviews for backend, platform, and cloud roles. Use the code snippets, run small experiments (especially with virtual threads), and back your answers with trade-offs and real-world constraints during interviews.
Next steps: convert parts of these Q&A into small hands-on labs — e.g., build a virtual-thread-based REST service, record-pattern exercises, and string-template playgrounds. Those projects demonstrate real experience and improve interview credibility.
❓ FAQ
Q: Is Java 21 ready for production?
Yes — Java 21 is an LTS release. Preview features should be used cautiously, and production systems should rely primarily on stable APIs.
Q: Should I rewrite blocking code to be reactive now?
Not necessarily. Evaluate whether virtual threads simplify your architecture. Reactive is still valuable for streaming and backpressure-sensitive systems.
Q: Will virtual threads replace platform threads?
No — platform threads are still used for OS interactions and certain low-level tasks. Virtual threads complement platform threads by enabling scalable blocking concurrency.
Q: Do I need to enable preview flags for string templates?
Yes — string templates are a preview feature in Java 21 and require compiler and JVM flags when used.