What Java Developer Interviews Test
Java developer interviews test ecosystem knowledge through java multithreading interview questions requiring thread synchronization and concurrency patterns, JVM interview questions testing memory management and garbage collection understanding, and Spring Boot interview scenarios demonstrating dependency injection and auto-configuration. Companies probe how you handle race conditions preventing data corruption, optimize JVM performance tuning heap settings, and build RESTful services using Spring framework leveraging annotations and conventions. For comprehensive technical interview preparation, visit our complete IT interview guide.
These java developer interview questions cover thread lifecycle understanding states from NEW to TERMINATED, memory areas including heap and stack allocation, Spring Boot starter dependencies simplifying configuration, and Java concurrency questions using ExecutorService and concurrent collections. Modern Java development emphasizes functional programming with lambdas and streams introduced in Java 8, reactive programming using Spring WebFlux for non-blocking I/O, and microservices architecture decomposing applications into independently deployable services.
Multithreading & Concurrency
Q: Explain the difference between Thread and Runnable in Java.
Thread is a class you extend to create threads: class MyThread extends Thread { public void run() {...} }. Runnable is an interface you implement: class MyTask implements Runnable { public void run() {...} }, then pass to Thread constructor: new Thread(new MyTask()).start(). Runnable is preferred because Java doesn’t support multiple inheritance, allowing your class to extend another class while still creating threads. Runnable also promotes better design separating task logic from thread management. Modern Java favors ExecutorService over direct Thread creation managing thread pools efficiently.
Q: What is synchronization and why is it needed?
Synchronization prevents race conditions when multiple threads access shared data concurrently. Without synchronization, thread interleaving can cause data corruption. Example: two threads incrementing counter simultaneously may both read 5, increment to 6, resulting in 6 instead of 7. The synchronized keyword ensures only one thread executes critical section at a time. Synchronized methods lock on object instance (this), synchronized blocks can lock on any object. Acquiring lock causes other threads to wait preventing concurrent modification. Over-synchronization causes performance bottlenecks so minimize synchronized scope to critical sections only.
Q: Describe the thread lifecycle in Java.
Threads progress through states: NEW (created but not started), RUNNABLE (executing or ready to execute), BLOCKED (waiting for monitor lock), WAITING (waiting indefinitely for another thread), TIMED_WAITING (waiting for specified time), TERMINATED (completed execution). Call start() moving thread from NEW to RUNNABLE. Thread scheduler decides when RUNNABLE threads actually execute. Threads enter BLOCKED when trying to acquire lock held by another thread. wait() moves to WAITING, notify() returns to RUNNABLE. sleep() or wait(timeout) causes TIMED_WAITING. Thread reaches TERMINATED after run() completes or throws uncaught exception.
Q: What’s the difference between wait() and sleep()?
wait() is called on objects inside synchronized blocks, releasing the lock allowing other threads to acquire it. Thread waits until notify() or notifyAll() called on same object. sleep() is called on Thread class, pausing execution for specified milliseconds without releasing locks. wait() for inter-thread communication and coordination. sleep() for timed delays. wait() throws InterruptedException and must be inside synchronized context. sleep() also throws InterruptedException but doesn’t require synchronization. Example: Producer-Consumer uses wait()/notify(), rate limiting uses sleep().
💡 Pro tip: Java multithreading interviews often include follow-up questions. When explaining synchronized, be ready to discuss volatile keyword, ReentrantLock alternatives, or concurrent collections like ConcurrentHashMap demonstrating deeper knowledge beyond basics.
JVM Internals & Memory Management
Q: Explain JVM memory areas and their purposes.
Heap stores objects and instance variables, shared across threads, managed by garbage collector. Stack stores method frames with local variables and method call information, one stack per thread, automatically managed when methods enter/exit. Method Area (Metaspace in Java 8+) stores class metadata, static variables, and constant pool, shared across threads. Program Counter Register tracks current instruction for each thread. Native Method Stack for native method calls. Understanding heap vs stack crucial: objects on heap, primitives and references on stack. Stack overflow occurs from excessive recursion, OutOfMemoryError from too many objects on heap.
Q: How does garbage collection work in Java?
Garbage collector automatically reclaims memory from unreachable objects preventing manual memory management errors. Objects unreachable from GC roots (static variables, active threads, JNI references) are eligible for collection. Generational GC divides heap into Young Generation (Eden + Survivor spaces) and Old Generation. Most objects die young so frequent minor GC on Young Generation is cheap. Long-lived objects promoted to Old Generation collected less frequently in major GC. GC algorithms include Serial, Parallel, CMS (Concurrent Mark Sweep), G1 (Garbage First), ZGC (low-latency). Tune GC with flags like -Xmx (max heap), -XX:+UseG1GC.
Q: What causes OutOfMemoryError and how do you debug it?
OutOfMemoryError occurs when JVM can’t allocate objects due to insufficient heap space or unable to create new threads. Common causes: memory leaks (objects referenced but not used), excessive object creation, large datasets loaded into memory, or inadequate heap size. Debug using heap dump analysis with tools like Eclipse MAT or VisualVM identifying objects consuming memory. Enable heap dump on error: -XX:+HeapDumpOnOutOfMemoryError. Check for common leaks: unclosed resources, static collections growing unbounded, listeners not removed. Increase heap size if truly needed: -Xmx4g, but fix leaks first.
Q: Explain the difference between stack and heap memory.
Stack memory stores method frames with local variables (primitives and object references) and method call information. Each thread has own stack, automatically managed following LIFO principle. Stack is fast but limited in size (typically 1MB per thread). Heap memory stores actual objects and instance variables, shared across all threads. Heap is larger (configurable via -Xmx) but slower than stack. Objects on heap persist until garbage collected. Example: int x = 5; stores value on stack, String s = new String("hello"); stores reference on stack, actual String object on heap.
Spring Boot & Framework
What is dependency injection and how does Spring implement it?
Dependency Injection (DI) provides object dependencies rather than having objects create them, promoting loose coupling and testability. Spring implements DI through Inversion of Control (IoC) container managing object lifecycle.
Use @Autowired annotation injecting dependencies automatically: @Autowired private UserRepository userRepo;.
Constructor injection preferred over field injection for immutability and testability: public UserService(UserRepository repo) { this.repo = repo; }.
Spring resolves dependencies at startup, throwing errors if beans not found or multiple candidates exist (use @Qualifier specifying which).
@Component, @Service, @Repository mark classes as Spring beans enabling auto-detection.
Explain Spring Boot auto-configuration.
Auto-configuration automatically configures Spring application based on dependencies on classpath. Add spring-boot-starter-web dependency, Spring Boot automatically configures Tomcat embedded server, Spring MVC, and JSON serialization. It checks classpath and existing beans, applying configuration only when needed.
@SpringBootApplication enables auto-configuration through @EnableAutoConfiguration.
Customize with application.properties or application.yml: server.port=8081.
Exclude auto-configurations: @SpringBootApplication(exclude = DataSourceAutoConfiguration.class).
View auto-configuration report enabling debug logging showing what was configured and why.
How do you create RESTful web services in Spring Boot?
Use @RestController combining @Controller and @ResponseBody returning JSON automatically.
Map HTTP methods: @GetMapping("/users"), @PostMapping("/users"), @PutMapping("/users/{id}"), @DeleteMapping("/users/{id}").
Path variables: @GetMapping("/users/{id}") public User getUser(@PathVariable Long id).
Request body: @PostMapping("/users") public User create(@RequestBody User user).
Request parameters: @GetMapping("/search") public List<User> search(@RequestParam String name).
Return ResponseEntity for full control over status codes and headers. Spring Boot automatically serializes objects to JSON using Jackson.
Advanced Concurrency & Collections
Q: What is ExecutorService and why use it over creating threads directly?
ExecutorService manages thread pool executing tasks asynchronously without creating new threads for each task. Create using Executors.newFixedThreadPool(5) reusing 5 threads, or newCachedThreadPool() creating threads as needed. Submit tasks: executorService.submit(() -> doWork()). Benefits include thread reuse reducing overhead, controlled concurrency limiting threads preventing resource exhaustion, and automatic thread lifecycle management. Provides Future for task results and cancellation. Always shut down: executorService.shutdown() or shutdownNow() preventing memory leaks. Prefer ExecutorService over raw threads for production code.
Q: Explain ConcurrentHashMap and how it differs from synchronized HashMap.
ConcurrentHashMap is thread-safe without synchronizing entire map, achieving better concurrency. It uses segmentation (Java 7) or CAS operations (Java 8+) allowing multiple threads to read/write different segments simultaneously. Synchronized HashMap locks entire map for every operation causing bottlenecks with high contention. ConcurrentHashMap provides atomic operations: putIfAbsent(), computeIfAbsent(), merge(). Iterators are weakly consistent reflecting some but not necessarily all concurrent modifications. Don’t use null keys or values unlike HashMap. For thread-safe collections, prefer concurrent versions: ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue over synchronized wrappers.
Q: What is deadlock and how do you prevent it?
Deadlock occurs when two or more threads wait indefinitely for locks held by each other. Example: Thread A holds Lock 1 waiting for Lock 2, Thread B holds Lock 2 waiting for Lock 1. Prevention strategies: Always acquire locks in same order across threads preventing circular wait. Use timeout with tryLock(timeout) abandoning if lock unavailable. Avoid nested locks when possible. Use higher-level concurrency utilities like ReentrantLock with try-finally for guaranteed unlock. Detect deadlocks using thread dumps (jstack) showing threads in BLOCKED state with lock dependencies. Design lock-free algorithms using atomic variables where appropriate.
Q: What is volatile keyword and when should you use it?
volatile ensures visibility of variable changes across threads. Without volatile, threads may cache variable values not seeing updates from other threads. volatile guarantees: Read always gets latest value from main memory, write immediately flushed to main memory. Use for flags: private volatile boolean running = true; ensuring other threads see updates. volatile provides visibility not atomicity; count++ is not atomic even with volatile. For atomic operations use AtomicInteger, AtomicLong. volatile is lighter than synchronized avoiding locking overhead but offers fewer guarantees. Consider for simple flags or state variables accessed by multiple threads.
⚠️ Common mistake: Thinking synchronized and volatile are interchangeable. synchronized provides both visibility and atomicity, locking critical sections. volatile only provides visibility without atomicity or mutual exclusion. Choose based on requirements: complex operations need synchronized, simple flags use volatile.
Java Ecosystem Practice
20 Practice Questions
1. Runnable vs Thread difference?
- No difference
- Runnable is interface, Thread is class
- Runnable is faster
- Thread is deprecated
2. synchronized keyword prevents?
- Memory leaks
- Race conditions in concurrent access
- Compilation errors
- Stack overflow
3. Heap memory is used for?
- Local variables only
- Objects and instance variables
- Method calls
- Class metadata
4. wait() must be called?
- Anywhere
- Inside synchronized block/method
- In main method only
- On Thread class
5. Spring @Autowired provides?
- Manual object creation
- Automatic dependency injection
- Thread synchronization
- Garbage collection
6. Garbage collector reclaims memory from?
- All objects
- Unreachable objects
- Null objects only
- Static objects
7. volatile keyword ensures?
- Atomicity
- Visibility across threads
- Synchronization
- Immutability
8. ExecutorService advantage over raw threads?
- Creates more threads
- Thread pool reuse and lifecycle management
- Runs faster
- No advantages
9. ConcurrentHashMap allows?
- Only one thread access
- Multiple threads concurrent read/write
- Null keys and values
- No thread safety
10. @RestController combines?
- @Service + @Repository
- @Controller + @ResponseBody
- @Component + @Bean
- @Entity + @Table
11. Thread states include?
- RUNNING only
- NEW, RUNNABLE, BLOCKED, WAITING, TERMINATED
- START, STOP
- ACTIVE, INACTIVE
12. Spring Boot auto-configuration based on?
- User preferences
- Dependencies on classpath
- Random selection
- Manual configuration only
13. sleep() vs wait() difference?
- No difference
- sleep() doesn’t release lock, wait() does
- sleep() is faster
- wait() is deprecated
14. Deadlock requires minimum?
- 1 thread, 1 lock
- 2 threads, 2 locks (circular wait)
- 3 threads
- Infinite threads
15. -Xmx flag sets?
- Stack size
- Maximum heap size
- Thread count
- GC algorithm
16. @GetMapping handles?
- POST requests
- HTTP GET requests
- Database queries
- File uploads
17. Stack memory stores?
- All objects
- Method frames, local variables, references
- Class metadata
- Garbage collection data
18. Constructor injection in Spring?
- Not supported
- Preferred for immutability and testability
- Slower than field injection
- Requires @Autowired always
19. notify() wakes up?
- All waiting threads
- One waiting thread (arbitrary)
- Main thread only
- No threads
20. Young Generation in GC contains?
- Old objects only
- Eden + Survivor spaces for new objects
- Static variables
- Class metadata
❓ FAQ
☕ What Java version should I focus on for interviews?
Most companies use Java 8, 11, or 17 (LTS versions). Focus on Java 8 features: lambdas, streams, Optional, functional interfaces since they’re universally used. Know basics of modules (Java 9+), var keyword (Java 10), and text blocks (Java 13+) but don’t need deep expertise in newer features. Understand version-specific changes like removal of permanent generation (Java 8), G1GC improvements (Java 9+). Check job description for version requirements. Companies gradually adopt newer versions so Java 8 knowledge remains valuable despite being older.
🔧 How deep should I know Spring Boot for Java developer roles?
Depends on role focus. Backend positions require solid Spring Boot knowledge: dependency injection, auto-configuration, REST API creation, Spring Data JPA, and configuration properties. Understand annotations like @SpringBootApplication, @RestController, @Service, @Repository, @Autowired. Know how to create starter project, build RESTful services, connect to databases. Microservices roles need Spring Cloud knowledge. Junior positions focus on using Spring Boot, senior roles on customizing auto-configuration and architectural decisions. Practice building simple CRUD application demonstrating core concepts during interviews.
🧵 How important is multithreading knowledge for Java interviews?
Very important for backend and system-level roles where concurrent requests are common. You’ll likely face basic questions (Thread vs Runnable, synchronized keyword, thread states) in most interviews. Senior positions probe deeper: deadlock prevention, ExecutorService usage, concurrent collections, memory visibility issues. Financial services and high-performance computing roles emphasize advanced concurrency. Web development roles need solid understanding but less deep expertise. Practice explaining concepts clearly over memorizing syntax. Understanding when to use concurrency and its tradeoffs matters more than knowing every concurrent utility class.
💾 Do I need to understand JVM internals for application development roles?
Basic JVM knowledge expected for all Java positions: heap vs stack, garbage collection concepts, common memory errors. You should explain how GC works at high level and basic tuning flags like -Xmx/-Xms. Deep JVM internals (bytecode, JIT compilation, GC algorithms) more relevant for performance engineering, large-scale systems, or companies with demanding applications. Interview preparation should cover memory areas, object lifecycle, and common OutOfMemoryError causes. Practical understanding trumps theoretical depth unless applying for specialized performance roles. Know enough to debug memory issues and optimize when needed.
📚 Should I learn Jakarta EE or stick with Spring for modern Java development?
Spring dominates modern Java development with Spring Boot making microservices and web applications straightforward. Most companies building new applications choose Spring ecosystem over Jakarta EE (formerly Java EE). Jakarta EE knowledge valuable for enterprise environments with legacy applications or government/finance sectors using application servers (WebLogic, WebSphere, WildFly). For career versatility, prioritize Spring Boot plus Spring Data, Spring Security. Learn Jakarta EE concepts (Servlets, EJB, JPA) at high level since Spring builds upon them. Focus interview preparation on Spring unless job specifically mentions Jakarta EE or application server experience.
Final Thoughts
Mastering java developer interview questions requires combining theoretical knowledge with practical coding ability demonstrated through working examples. The best preparation includes practicing multithreading concepts with actual code creating threads, implementing synchronization, and handling race conditions rather than just reading about them. Understanding JVM fundamentals helps debugging production issues and optimizing application performance beyond passing interviews. Focus on explaining concepts clearly using real-world analogies since interviewers value communication skills alongside technical knowledge.
Companies value Java developers who understand the ecosystem beyond syntax: why Spring Boot simplifies configuration through convention over configuration, when to use concurrent collections versus synchronized wrappers, and how garbage collection impacts application behavior. Your preparation should include building small projects demonstrating Spring Boot REST services, practicing multithreading scenarios with ExecutorService, and experimenting with JVM flags observing their effects. Demonstrate both breadth across Java platform and depth in areas matching role requirements whether backend services, enterprise applications, or distributed systems development.
⚠️ Disclaimer: The interview strategies, sample answers, and negotiation tips provided in this guide are for educational purposes only. Hiring decisions are subjective and vary by company and industry. While these strategies are based on professional HR standards, they do not guarantee a specific job offer or result.








