Check your interview readinessStart Tech Assessment

Java Interview Questions

JVM internals, collections, concurrency and memory - the Java questions asked from mid to senior level.

10 min readUpdated Jul 2026By the TopCoding team

Java interviews at mid-to-senior level expect you to reason about the JVM, not just write syntax. The questions below cover what interviewers actually probe - from garbage collection and the Java Memory Model to the nuances of the collections framework and the Streams API.

JVM
Shared runtime targeted by Java, Kotlin, Scala and Groovy - understand it once
Java 17
Current LTS - know records, sealed classes and text blocks alongside classics
G1 GC
Default garbage collector since JDK 9 - the one interviewers mean unless specified

JVM and garbage collection

The JVM is the foundation every Java question rests on. Understanding how memory is laid out and how objects are reclaimed explains a large class of performance and correctness issues.

QuestionSharp answer
What are the JVM memory areas?Heap (object instances and arrays, GC-managed), Metaspace (class metadata, replaces PermGen since Java 8), Stack (one per thread - frames for method calls, local variables, operand stack), PC register, and native method stack.
How does generational GC work?Most objects die young (weak generational hypothesis). The heap is split into Young (Eden + two Survivor spaces) and Old (Tenured). Minor GC collects Young quickly; Major/Full GC collects Old. Objects that survive several Minor GCs are promoted to Old.
What is G1 GC?Garbage-First divides the heap into equal-sized regions rather than fixed generational areas. It collects the regions with the most garbage first, which lets it meet soft pause-time goals. Default since JDK 9.
What triggers an OutOfMemoryError?Heap exhaustion (too many live objects), Metaspace exhaustion (too many loaded classes, common with reflection or class-loader leaks), or a StackOverflowError from deep/infinite recursion (technically a different error but often conflated).
What is the difference between the stack and the heap?Stack memory is thread-local, holds primitive local variables and references (not the objects they point to), and is freed automatically when a frame pops. Heap memory holds all object instances and is shared across threads; it is GC-managed.
JVM flags worth knowing
Interviewers at infrastructure-focused companies may ask about -Xms/-Xmx (initial/max heap), -XX:+UseG1GC, and -XX:MaxGCPauseMillis. Know what they do; you don't need to memorise every flag.

Collections framework

Choosing the wrong collection is a red flag. Know the concrete implementations, their complexity guarantees, and the trade-offs.

TypeImplementationWhen to use
ListArrayListRandom access, end-appends. O(1) get/set, O(n) insert-at-index.
ListLinkedListFrequent insert/remove at head or interior. O(1) at known node, O(n) index lookup. Rarely the right call in practice.
MapHashMapO(1) average get/put. No ordering guarantee. Allows one null key.
MapLinkedHashMapInsertion-order or access-order iteration over a HashMap. Useful for LRU caches.
MapTreeMapO(log n) operations, keys sorted by natural order or Comparator. Use when you need floorKey/ceilingKey/subMap.
SetHashSetO(1) average contains/add. No ordering. Backed by a HashMap.
SetTreeSetO(log n), sorted. Backed by a TreeMap.
QueuePriorityQueueMin-heap by default. O(log n) offer/poll, O(1) peek. Pass a Comparator for max-heap or custom ordering.
DequeArrayDequeO(1) amortised push/pop at both ends. Preferred over Stack and LinkedList for stack/queue use.
Map (concurrent)ConcurrentHashMapThread-safe, higher concurrency than Hashtable (segment-level locking in Java 7, CAS in Java 8+). Never use Hashtable in new code.
The interview litmus test
If an interviewer says "use a map", your first question should be: do I need ordering? If yes, TreeMap. Do I need concurrency? ConcurrentHashMap. Otherwise, HashMap. State that reasoning out loud.

Concurrency

Java concurrency questions range from threading fundamentals to the Java Memory Model. This is a deep area; know the vocabulary and the modern APIs.

QuestionSharp answer
What does synchronized do?Acquires a monitor lock on the object (or class for static methods) before entering the block/method, ensuring mutual exclusion and establishing a happens-before relationship for memory visibility.
What is volatile?Guarantees visibility: reads/writes go directly to main memory, not a CPU cache. It does NOT make compound actions (check-then-act, increment) atomic. Use AtomicInteger or synchronized for compound operations.
What is the Java Memory Model?The JMM defines which memory operations are visible to which threads. It specifies happens-before relationships: a write that happens-before a read guarantees the read sees the write. Actions that establish happens-before: synchronized unlock/lock, volatile write/read, thread start, thread join.
ExecutorService vs raw threads?ExecutorService decouples task submission from thread management. It maintains a thread pool, handles reuse, and exposes Future for results. Always prefer it over new Thread() - raw threads leak easily and lack backpressure.
What is a race condition vs a deadlock?Race condition: outcome depends on thread scheduling - typically from unsynchronized reads/writes to shared mutable state. Deadlock: two or more threads each hold a lock and wait for the other, blocking forever. Prevent deadlock by acquiring locks in a consistent global order.
ReentrantLock vs synchronized?ReentrantLock from java.util.concurrent.locks offers tryLock (non-blocking acquisition), timed lock, fairness policy, and multiple Condition variables. synchronized is syntactically simpler and sufficient for most cases; use ReentrantLock when you need those extras.
java.util.concurrent
Know these classes cold
CountDownLatch, CyclicBarrier, Semaphore, BlockingQueue, CompletableFuture, AtomicInteger/Long/Reference. Each solves a specific coordination problem - know the use case for each.
Virtual threads (Java 21)
Project Loom changes the calculus
Virtual threads are lightweight, JVM-scheduled threads that make blocking I/O cheap again. One virtual thread per task is idiomatic - no executor pool tuning needed. Know this for 2024+ interviews.

equals / hashCode contract

Violating this contract silently breaks HashMap, HashSet, and any collection that relies on hashing. Interviewers test it because many engineers get it wrong.

RuleWhy it matters
If a.equals(b) then a.hashCode() == b.hashCode()HashMap uses hashCode to find the bucket, then equals to find the key. If equal objects have different hashCodes, the map will not find a previously stored key.
The converse is NOT requiredTwo unequal objects may have the same hashCode (collision). HashMap handles this with chaining or tree bins (Java 8+). A function that returns 42 for everything is a valid but terrible hashCode.
Override both or neitherThe default Object.equals is identity (==); the default Object.hashCode is based on memory address. If you override equals to compare by fields, you must override hashCode to maintain the contract.
equals must be reflexive, symmetric, transitive, consistent, and handle nullx.equals(null) must return false (not throw). Consistency means the result must not change between calls unless a field used in comparison is mutated.

Generics and type erasure

QuestionSharp answer
What is type erasure?Generic type parameters are removed at compile time and replaced with their bounds (Object if unbounded). At runtime, List<String> and List<Integer> are both just List. This preserves backwards compatibility with pre-generics bytecode.
Why can&apos;t you do new T()?Because T is erased at runtime - the JVM doesn&apos;t know what type T is. Workaround: pass a Class<T> parameter and call clazz.getDeclaredConstructor().newInstance(), or use a factory lambda.
What is bounded wildcarding? When do you use ? extends vs ? super?PECS - Producer Extends, Consumer Super. Use List<? extends Animal> when you only read from the list (producer). Use List<? super Dog> when you only write to it (consumer). A list of both reads and writes needs a concrete type parameter.
Can you check instanceof against a generic type at runtime?No. obj instanceof List<String> is a compile error because List<String> is erased. You can check obj instanceof List<?> but not the element type.

Checked vs unchecked exceptions

AspectCheckedUnchecked
SuperclassException (but not RuntimeException)RuntimeException or Error
Compile-time enforcementMust catch or declare in throwsNo requirement
Typical useRecoverable external failures: IOException, SQLExceptionProgramming errors: NullPointerException, IllegalArgumentException, IndexOutOfBoundsException
Streams / lambdasCannot be thrown from a lambda without wrapping - a common pain pointPropagate freely from lambdas
Modern trendLibraries (Spring, Hibernate) increasingly wrap checked exceptions in unchecked ones to avoid API pollutionDominant in modern code
Swallowing exceptions
catch (Exception e) is always wrong in production code. If you can't handle it, re-throw it (possibly wrapped in an unchecked exception) or log and rethrow. Interviewers watch for this in code reviews.

Streams API

The Streams API (Java 8+) is tested in coding rounds as well as language questions. Know both the semantics and the performance traps.

QuestionSharp answer
What is a Stream?A lazily evaluated pipeline over a sequence of elements. It is not a data structure - it does not store elements. A pipeline has a source, zero or more intermediate operations (map, filter, sorted), and one terminal operation (collect, reduce, forEach). Intermediate operations are lazy; the terminal operation triggers execution.
map vs flatMap?map applies a function 1-to-1, producing Stream<Stream<T>> if the function returns a collection. flatMap applies the function and flattens one level - each element maps to a Stream and those streams are concatenated.
When are parallel streams appropriate?Only when: the data set is large (thousands of elements minimum), the per-element work is CPU-bound and stateless, and the source splits well (ArrayList yes, LinkedList no). The overhead of the ForkJoinPool makes parallel streams slower than sequential for small or I/O-bound workloads.
collect vs reduce?reduce folds elements into a single immutable result using an identity and a BinaryOperator. collect is a mutable reduction that accumulates into a container (List, Map, StringBuilder) using a Collector. Use collect for building collections; reduce for computing a scalar.
Can a Stream be reused?No. A Stream is consumed once. Attempting a second terminal operation throws IllegalStateException. If you need to traverse the source again, create a new Stream.
Practice these in a mock setting
Java internals questions are harder to answer live than they look on paper. If you want targeted feedback from engineers who currently run Java rounds at top companies, book a free call and we'll identify the gaps.

For the algorithm side of Java interviews, the patterns in LeetCode Patterns apply equally in Java - knowing when to reach for a PriorityQueue or a HashMap is just as important as knowing their internal details.

Sources & further reading

  1. 1The Java Language Specification, SE 21Oracle / OpenJDK
  2. 2java.util.concurrent package documentationOracle Java SE 21 API
  3. 3Collections framework overviewOracle Java Tutorials
  4. 4JEP 444: Virtual ThreadsOpenJDK