Skip to content

Java Developer interview questions

100 real questions with model answers and explanations for Senior candidates.

See a Java Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

springcontainersjvm

I would size the whole process first and load-test several heap points rather than assign all 8 GiB to `-Xmx`.

  • Reserve measured space for metaspace, code cache, thread stacks, direct buffers, native libraries, and roughly 10% to 15% container headroom.
  • Start near `-Xms4g -Xmx4g`, then compare allocation stalls, GC CPU, live-set margin, pause percentiles, RSS, and p99 under sustained 1.2 GiB/s allocation.
  • Keep the smallest heap that meets 120 ms p99 and throughput without old-generation growth or container memory pressure.

Why interviewers ask this: The interviewer is checking whether heap sizing follows the complete process budget, live set, allocation rate, and service latency.

memorydata-structures

I would benchmark ZGC first because a 10 ms pause target on 32 GiB favors concurrent relocation, while keeping G1 as the throughput baseline.

  • ZGC usually keeps pauses short across large heaps but consumes concurrent CPU and extra memory, so the available 25% headroom must be verified.
  • G1 may deliver better throughput if its young and mixed collections remain below 10 ms with the measured live set and allocation rate.
  • The decision uses p99 and p99.9 pauses, application throughput, GC CPU, RSS, allocation stalls, and recovery after traffic bursts.

Why interviewers ask this: A strong answer selects a collector from heap scale, pause objective, and measured CPU cost rather than reputation.

memorydata-structures

I would capture a steady workload and unified GC logs before changing one flag at a time.

  • Record allocation rate, live set after full marking, young and mixed pause distributions, remembered-set work, promotion, evacuation failures, concurrent-cycle timing, and GC CPU.
  • Lowering `MaxGCPauseMillis` can shrink young collections and increase their frequency, while manual young sizing can fight G1 ergonomics.
  • A change stays only if end-to-end p99, throughput, and CPU improve across warm-up, steady state, and old-generation pressure.

Why interviewers ask this: The interviewer is evaluating whether G1 tuning is driven by phase-level telemetry and application outcomes instead of flag folklore.

memorydata-structures

I would test Generational ZGC when most objects die young and non-generational ZGC spends unnecessary work scanning the whole allocation stream.

  • Enable the supported Java 21 option in an isolated benchmark and keep identical heap, workload, warm-up, and container limits for comparison.
  • Measure pause percentiles, allocation stalls, concurrent GC CPU, remembered-set overhead, live-set recovery, throughput, and RSS over several hours.
  • Adopt it only if the 3 GiB/s workload gains CPU or throughput without regressing latency or operational supportability.

Why interviewers ask this: A strong answer connects generational collection to object lifetime distribution and validates the Java 21 implementation empirically.

pricing

I would keep the temporary objects local and nonescaping so C2 can scalar-replace them after inlining.

  • Returning the object, storing it in a field, passing it to opaque code, or losing inlining can make the allocation escape and remain on the heap.
  • JFR or async-profiler allocation profiles verify whether compiled code still allocates, while JIT compilation logs explain failed inlining or deoptimization.
  • A JMH benchmark with consumed results and warmed forks must show lower allocation and equal behavior before rewriting readable domain code.

Why interviewers ask this: The interviewer is checking whether escape analysis is understood as a JIT optimization with observable preconditions, not a source-level guarantee.

I would reduce allocation only in measured hot paths because 900 MiB/s still consumes GC CPU and memory bandwidth even with short pauses.

  • TLAB makes individual allocations cheap, but refills, young-region turnover, survivor copying, and promotion consume shared resources.
  • Profile bytes and objects by allocation site, then target boxing, temporary collections, string formatting, and oversized buffers with clear ownership.
  • Accept the change only if CPU, throughput, or capacity improves without unsafe pooling or a readability cost larger than the gain.

Why interviewers ask this: A strong answer recognizes allocation throughput as a resource cost without equating every young object with a performance bug.

I would separate time to reach the safepoint from the 12 ms stop-the-world operation.

  • Threads in native calls, long counted loops, or paths with delayed polling can postpone global synchronization even when collector work is short.
  • Safepoint logs, JFR thread states, and stack samples identify the slow thread and whether JNI, compiler activity, or a diagnostic action is involved.
  • The fix targets the blocking native or polling path; changing collector pause flags cannot remove 168 ms spent reaching the safepoint.

Why interviewers ask this: The interviewer is evaluating whether the candidate can diagnose JVM pauses that occur before garbage-collector work.

cachingmemorydata-structures

I would compare dominators and GC-root paths at equivalent workload points and relate growth to an explicit retention policy.

  • A leak typically grows through listeners, static collections, thread locals, class loaders, or keys that should have expired.
  • A legitimate cache should have a configured maximum, eviction metrics, hit value, and retained size correlated with expected key cardinality.
  • MAT histograms and dominator deltas identify the owners of the extra 2.3 GiB, while forced full GC only confirms reachability, not usefulness.

Why interviewers ask this: A strong answer separates object reachability from business usefulness and uses comparable heap evidence.

designdeployment

I would give each deployment one disposable child class loader and remove every strong reference when the plugin stops.

  • Threads, thread locals, JDBC drivers, logging registries, executors, MBeans, and static parent caches commonly retain old loaders.
  • Class-unload and Native Memory Tracking metrics plus `jcmd VM.classloader_stats` verify whether loader generations disappear after full marking.
  • A churn test must load and unload well beyond 400 versions with bounded metaspace before the lifecycle is accepted.

Why interviewers ask this: The interviewer is checking whether class unloading is designed around loader reachability and common framework retention points.

containersconcurrency

I would treat the 2 GiB as a measured native budget, not guaranteed spare memory.

  • Account for direct buffers, metaspace, JIT code cache, thread stacks, GC structures, JNI libraries, memory mappings, and allocator fragmentation.
  • Monitor RSS, NMT categories, Netty allocator metrics, thread count, and `BufferPoolMXBean`, then cap direct memory and pools from the observed peak.
  • Leave container headroom for bursts and kernel accounting; if the native peak exceeds the budget, reduce heap or concurrency rather than wait for an OOM kill.

Why interviewers ask this: A strong answer sizes the entire JVM process and connects off-heap consumers to container enforcement.

gateway

I would use the networking library's bounded direct-buffer pool if profiling shows copy or allocation cost, not build an unbounded custom pool.

  • Direct buffers reduce native I/O copies but have allocation and cleanup costs and consume memory outside the Java heap.
  • Size arenas and maximum retained capacity from concurrency and payload percentiles, and reject oversized buffers from returning to common pools.
  • Compare throughput, CPU, RSS, allocator fragmentation, pool hit rate, and tail latency against heap buffers under 40,000 RPS.

Why interviewers ask this: The interviewer is evaluating whether off-heap pooling is bounded by workload and measured against its native-memory risks.

I would separate startup capacity from steady-state capacity and warm the real hot paths before declaring a replica ready.

  • JFR and compilation logs show tiered compilation, code-cache pressure, inlining, uncommon traps, and methods repeatedly deoptimized.
  • A representative warm-up must preserve branch and type profiles; synthetic calls that exercise different receivers can produce misleading compiled code.
  • Capacity planning includes 90-second readiness, rollout surge, and cold-replica routing, while tuning compiler flags is secondary to fixing unstable profiles.

Why interviewers ask this: A strong answer connects adaptive compilation behavior to readiness, benchmarking, and real traffic profiles.

jvmmemorydata-structures

I would check whether the larger heap disabled compressed ordinary object pointers or changed object alignment.

  • Compressed oops often work below a JVM-dependent addressable threshold near 32 GiB, reducing reference and header width.
  • `jcmd VM.info`, startup logs, JOL, and a class histogram confirm pointer mode and actual object layout rather than relying on the nominal threshold.
  • Compare total RSS, live-set bytes, cache locality, pause behavior, and p99; a 40 GiB heap can provide less effective capacity than expected.

Why interviewers ask this: The interviewer is checking knowledge of compressed references and why a larger heap can increase every object's cost.

immutabilityrecordsprimitives

I would benchmark a primitive-oriented layout because 30 million object headers and references can dominate the actual price data.

  • Records improve immutability and API clarity but remain heap objects and do not automatically remove headers or pointer chasing.
  • Parallel primitive arrays or a packed off-heap structure improve density and locality but add indexing, lifecycle, and safety complexity.
  • Choose from measured bytes per entry, scan throughput, update pattern, GC pressure, serialization cost, and maintainability.

Why interviewers ask this: A strong answer distinguishes language-level compact syntax from physical memory layout and quantifies the scale.

load-testingasync

I would record low-overhead JFR continuously and trigger async-profiler during a reproduced burst for higher-resolution stacks.

  • JFR correlates CPU, allocation, locks, threads, GC, safepoints, I/O, and application events on one timeline.
  • async-profiler adds wall-clock, CPU, allocation, and lock flame graphs with AsyncGetCallTrace or perf-based sampling that avoids safepoint bias.
  • The same 30-second window and request IDs must connect hot stacks to latency, otherwise a flame graph can optimize unrelated background work.

Why interviewers ask this: The interviewer is evaluating whether profiling tools are combined according to time correlation and stack-resolution needs.

concurrencyconfigmemory

I would publish an immutable configuration through a volatile reference or another explicit happens-before edge.

  • A volatile write of the reference happens-before later volatile reads, making all prior constructor writes visible to readers.
  • Final fields add initialization guarantees only when `this` does not escape during construction; they do not publish the reference by themselves.
  • Replacing the complete object avoids readers observing a mix of old and new values across its fields.

Why interviewers ask this: A strong answer applies happens-before to a concrete publication path instead of describing visibility abstractly.

concurrencymonitoring

I would use `LongAdder` when high write throughput matters more than an atomic instantaneous total.

  • `AtomicLong` performs CAS on one cache line, so retries and coherence traffic rise sharply under 32-core contention.
  • `LongAdder` spreads updates across cells and sums them on read, trading extra memory and non-linearizable snapshots for write scalability.
  • A JMH contention benchmark plus the metric's accuracy contract decides whether the 8-million-per-second gain is useful.

Why interviewers ask this: The interviewer is checking whether atomicity strength is traded deliberately for contention scalability.

concurrency

I would start with `synchronized` for simple mutual exclusion and choose `ReentrantLock` only for a required capability proven by contention tests.

  • `ReentrantLock` adds timed and interruptible acquisition, multiple conditions, and optional fairness, which can reduce throughput.
  • Forty microseconds times 32 contenders may make lock partitioning or shorter critical sections more valuable than lock implementation choice.
  • JFR lock events and a production-shaped benchmark compare wait time, throughput, p99, and cancellation behavior.

Why interviewers ask this: A strong answer avoids treating lock classes as performance rankings and first addresses contention structure.

concurrency

I would keep slow I/O outside the map's atomic computation and store a short-lived future or promise per key.

  • The first caller installs a `CompletableFuture`, performs loading on a bounded executor, and followers share the same result without duplicate calls.
  • Failures remove or expire the placeholder deliberately so one exceptional future does not poison the key forever.
  • Bound total in-flight loads and measure bin contention, duplicate suppression, loader p99, memory, and timeout behavior at 5,000 keys per second.

Why interviewers ask this: The interviewer is evaluating safe compound map operations without executing slow work inside internal synchronization.

concurrency

The rough blocking ratio suggests about 160 runnable and waiting threads for full CPU utilization, but throughput demand makes the downstream capacity the real bound.

  • The estimate is 16 times 1 plus 45 divided by 5, yielding about 160 threads before scheduling and memory overhead.
  • At 2,000 RPS and 45 ms wait, Little's Law gives roughly 90 concurrent I/O operations, which must fit connection pools and downstream limits.
  • Load-test queue delay, CPU, thread count, connection use, p99, and rejection, then use a bounded queue rather than absorb unlimited work.

Why interviewers ask this: A strong answer combines the blocking-ratio heuristic with Little's Law and downstream constraints.

Locked questions

  • 21

    A request fans out to six services through `CompletableFuture` and has a 300 ms deadline. How would you structure the futures?

    estimationconcurrency
  • 22

    A Java 21 API performs one 80 ms blocking HTTP call per request and targets 50,000 concurrent requests. Would you use virtual threads?

    concurrencyhttpapi
  • 23

    A virtual-thread service can create 100,000 tasks, but PostgreSQL allows only 120 connections. How do you enforce the boundary?

    concurrencypostgres
  • 24

    A library submits blocking work to `ForkJoinPool.commonPool`, and 24 CPU-bound parallel-stream tasks share it. What would you change?

  • 25

    An inventory service serializes updates per SKU across 10 million SKUs. Would you create one lock per key?

    serialization
  • 26

    Thirty-two worker threads update independent counters, yet throughput stops scaling after eight cores. How would you test for false sharing?

    concurrencyscalingthroughput
  • 27

    A transfer operation needs locks on two of 1 million accounts. How would you prevent deadlock while preserving concurrency?

    concurrencylocking
  • 28

    A Spring Boot service has 260 beans and three alternative payment implementations. How would you make dependency injection explicit and testable?

    springinjectiondependencies
  • 29

    A public method calls another method in the same Spring bean annotated with `@Transactional`, but the second transaction policy is ignored. Why?

    transactionsspring
  • 30

    An order transaction calls an audit write that must survive order rollback. Would you use `REQUIRES_NEW`?

    transactionsrollback
  • 31

    Two requests read stock 10 and each subtract 7 under `READ_COMMITTED`. How would you prevent overselling?

  • 32

    A Spring service must commit an order and publish an event at 8,000 orders per second without two-phase commit. How would you use an outbox?

    spring
  • 33

    Choose Spring MVC with virtual threads or WebFlux for an API making three blocking JDBC calls and serving 15,000 concurrent requests.

    concurrencyapispring
  • 34

    A WebFlux endpoint produces 1,000 events per second, but an SSE client consumes 50 and each connection may buffer only 64 MiB. How would you model backpressure?

    backpressureendpoints
  • 35

    A Kubernetes deployment has 80 Spring pods and PostgreSQL permits 600 application connections. How would you size HikariCP?

    kubernetesdeploymentpostgres
  • 36

    A Spring Boot application must start in 800 ms for scale-to-zero workloads. What would you measure before choosing AOT or another framework?

    spring
  • 37

    Forty Spring services share 120 configuration keys across four environments. How would you prevent silent misconfiguration?

    springconfig
  • 38

    A checkout call has a 900 ms deadline and invokes a dependency with p99 of 220 ms. How would you compose Resilience4j timeout, retry, circuit breaker, and bulkhead?

    resiliencedependenciesestimation
  • 39

    A `@Cacheable` method serves 50,000 reads per second, and entries must reflect price changes within 10 seconds. How would you design it?

    designcaching
  • 40

    A Java API spends 38% CPU in `BigDecimal` construction and formatting at 30,000 RPS. How would you optimize it?

    optimizationapi
  • 41

    An async-profiler allocation flame graph shows 6 million boxed `Long` objects per second from a Stream pipeline. What would you change?

    ci-cdasync
  • 42

    You need to compare two Java parsers that each finish in roughly 300 ns. How would you construct the JMH benchmark?

  • 43

    At 20,000 RPS, debug logging constructs 4 KiB JSON messages even when the level is disabled. How would you remove the cost?

    logging
  • 44

    A 64-thread benchmark spends 37% of wall time waiting on one lock. What would you do before replacing it with lock-free code?

    concurrency
  • 45

    An order API accepts 12,000 commands per second, and clients retry for 24 hours. How would you implement idempotency?

    idempotencyresilience
  • 46

    An order service writes 5,000 orders per second, while reporting joins take 2 seconds and may be 5 seconds stale. Would you introduce CQRS?

    joinscqrs
  • 47

    A Kafka-backed Spring processor must handle 60,000 events per second while preserving order per customer. How would you choose partitions?

    kafkaspringpartitioning
  • 48

    A Spring call chain has a 700 ms deadline and three services each configured for two retries. How would you prevent retry amplification?

    resiliencespringconfig
  • 49

    One downstream handles 300 concurrent calls, but your 40 Spring pods can generate 4,000. How would you apply bulkheads and a circuit breaker?

    resiliencespringconcurrency
  • 50

    A pricing service has 30 country-specific rule sets that change weekly. Which pattern would you use instead of a 2,000-line conditional method?

    pricing
  • 51

    A Spring service's heap grows from 2 GiB to 11 GiB over four days and restarts nightly. How do you investigate the leak?

    springdata-structuresmemory
  • 52

    Old-generation occupancy remains at 92% after mixed collections, but request volume is stable. What do you do before increasing `-Xmx`?

    collections
  • 53

    A 14 GiB heap OOMs during a two-minute traffic burst, but no heap dump is written because the disk is full. How do you recover useful evidence?

    memorydata-structures
  • 54

    Kubernetes OOM-kills a Java pod at 8 GiB while heap usage stays below 4.5 GiB. Netty direct memory reaches 2.1 GiB. How do you respond?

    memorykubernetesdata-structures
  • 55

    Metaspace grows 120 MiB after every application redeploy and reaches its limit after six deploys. How do you find the class-loader leak?

    deployment
  • 56

    After a release, G1 stop-the-world p99 rises from 45 ms to 480 ms on a 24 GiB heap. How do you diagnose it?

    memorydata-structures
  • 57

    A ZGC service keeps pauses below 5 ms but shows allocation stalls and CPU rising from 58% to 91%. What do you inspect?

  • 58

    G1 logs show 900 humongous allocations per minute after payload size increases from 400 KiB to 3 MiB. What would you change?

  • 59

    A batch service starts full GC every 70 seconds after survivor promotion triples. How do you find the cause?

    batch
  • 60

    A service fails with `unable to create native thread` at 18,000 threads while heap is healthy. How do you stabilize it?

    concurrencydata-structuresmemory
  • 61

    All 240 Tomcat threads are waiting on one downstream, the executor queue has 18,000 tasks, and API p99 is 14 seconds. What do you do?

    concurrencydata-structuresapi
  • 62

    Blocking SDK calls occupy the `ForkJoinPool.commonPool`; 96% of `CompletableFuture` tasks wait and CPU is 22%. How do you fix it?

    concurrency
  • 63

    HikariCP has 30 active connections, 400 waiting requests, and a 5-second acquisition timeout while PostgreSQL CPU is 95%. How do you respond?

    postgresresilience
  • 64

    A Java 21 service uses virtual threads, but JFR shows 80 carrier threads pinned for 600 ms inside a synchronized block. What do you change?

    concurrency
  • 65

    Two order threads are deadlocked; `jstack` shows each owns one account monitor and waits for the other. How do you eliminate it?

    concurrencylockingmonitoring
  • 66

    JFR shows 43% of request time contending on one `ReentrantLock`, and p99 rises from 90 to 780 ms at 64 threads. What do you do?

    concurrency
  • 67

    A `ConcurrentHashMap.computeIfAbsent` function performs a 900 ms HTTP call, and unrelated cache requests stall. How do you repair it?

    concurrencyhttpcaching
  • 68

    An unbounded executor queue grows to 2.4 million tasks and consumes 9 GiB while workers process only 8,000 tasks per second. How do you recover?

    concurrencydata-structures
  • 69

    A scheduled job takes 75 seconds but runs every 60 seconds, creating 180 overlapping executions after three hours. How do you fix it?

  • 70

    A WebFlux service has low CPU, but event-loop threads spend 1.4 seconds inside a JDBC driver and 6,000 requests queue. How do you stabilize it?

    concurrencydata-structuresjdbc
  • 71

    A release raises API p99 from 180 ms to 1.9 seconds while median changes by only 20 ms. How would you use JFR to find it?

    api
  • 72

    CPU reaches 100% after a validation release, and async-profiler attributes 46% to one regular expression. What do you change?

    asyncregexvalidation
  • 73

    Allocation jumps from 450 MiB/s to 2.8 GiB/s after a JSON-library upgrade, increasing GC CPU by 19 points. How do you decide whether to revert?

  • 74

    Loading 500 orders triggers 501 SQL statements through Hibernate and raises endpoint latency to 2.6 seconds. How do you remove the N+1?

    sqln+1orm
  • 75

    A JPA repository query scans 18 million rows and takes 4.2 seconds after a new optional filter is added. How do you optimize it?

    queriesormoptimization
  • 76

    A Spring Data import inserts 2 million rows at 1,100 rows per second and uses 10 GiB of heap. How do you improve it?

    springdata-structuresmemory
  • 77

    A controller starts throwing `LazyInitializationException` after `open-in-view` is disabled. How do you repair the boundary?

  • 78

    PostgreSQL reports deadlocks between two Spring transactions that update orders and inventory in opposite order. How do you fix them?

    transactionspostgreslocking
  • 79

    A popular cache key expires and 3,000 requests simultaneously query PostgreSQL, taking the database to 100% CPU. How do you stop the stampede?

    databasequeriespostgres
  • 80

    A logging change raises allocation by 700 MiB/s and p99 by 240 ms even though debug logging is disabled. What do you inspect?

    logging
  • 81

    A rolling deploy fails with `NoSuchMethodError` only on 30% of pods after a library upgrade. How do you find the dependency conflict?

    deploymentdependencies
  • 82

    After a Spring Boot 3 upgrade, requests fail with `ClassNotFoundException: javax.servlet.Filter` on 60 services. What is your migration response?

    migrationsspring
  • 83

    A hot-reload platform returns the wrong implementation after 40 redeploys, and old class loaders remain reachable. What do you do?

  • 84

    A Spring release starts with two `PaymentClient` beans and fails because one module lost its qualifier. How do you prevent this across 70 services?

    spring
  • 85

    Moving from Java 17 to 21 causes an older framework to fail reflective access on startup in 25 services. What do you do?

  • 86

    A native-image deployment starts in 70 ms but fails only on one reflection-based serializer in production. How do you recover?

    serializationdeployment
  • 87

    A rolling deploy mixes two Java versions, and serialized session objects fail on 18% of requests. How do you repair compatibility?

    sessionsdeploymentserialization
  • 88

    A timeout property intended as 500 ms is parsed as 500 seconds on 12 services after a config migration. How do you contain it?

    migrationsconfigresilience
  • 89

    A Resilience4j retry change turns 6,000 requests per minute into 31,000 attempts while the dependency is slow. How do you stop the storm?

    resiliencedependencies
  • 90

    Kafka lag reaches 18 million records because one tenant owns 62% of a partition's traffic. How do you address the hot key?

    partitioningkafkarecords
  • 91

    An outbox table accumulates 24 million rows and events are 47 minutes late although order commits succeed. How do you recover?

  • 92

    A payment endpoint charges 126 customers twice after clients retry timed-out requests. How do you respond?

    resilienceendpoints
  • 93

    A circuit breaker opens after five failures on a service handling 40,000 requests per second and sends 70% of traffic to a costly fallback. What do you change?

    resilience
  • 94

    A Kafka producer adds a required field, and 9 of 34 consumers fail deserialization during rollout. How do you recover?

    kafka
  • 95

    A mid-level engineer responds to a leak by increasing heap from 4 to 12 GiB, and restarts move from daily to every three days. How do you mentor them?

    mentoringdata-structuresmemory
  • 96

    A Java engineer uses `parallelStream()` for 300 blocking calls and starves unrelated futures. How do you redirect the design?

    design
  • 97

    A junior engineer fixes a race by marking a method `synchronized`, cutting throughput from 22,000 to 3,100 RPS. What do you do?

    throughputconcurrency
  • 98

    Two senior engineers want to rewrite a blocking JDBC API in WebFlux after p99 reaches 1.6 seconds. How do you resolve the proposal?

    jdbcapi
  • 99

    A teammate wants to deploy a Hibernate migration today, but its load test issues 14 times more SQL statements. How do you handle the deadline?

    sqlmigrationsorm
  • 100

    A Java platform outage costs $430,000 after a memory leak, retry storm, and missing heap dump cross three teams. How do you run the postmortem?

    memoryresiliencedata-structures