Java remains the dominant backend language in Indian BFSI technology (banking, insurance, capital markets) and is widely used at enterprise product companies like SAP, Oracle, and Freshworks. Senior Java interviews go deep on JVM internals, concurrency primitives, and Spring Boot architecture. This guide covers the advanced Java topics that differentiate senior candidates in India in 2026.
Senior Java developer salary in India 2026
Senior Java developer salary in India (2024-25):
Java developer (2-4 years, mid-level): 12-28 LPA at product companies; 8-18 LPA at IT services. Senior Java developer (5-8 years): 25-55 LPA at product companies; 18-35 LPA at IT services. Java architect (8-12 years): 40-80 LPA at product companies. Principal/Staff Java engineer (12+ years at top product companies): 70-150 LPA TC.
Highest-paying Java roles in India:
- BFSI technology (banking, insurance, capital markets): Java Spring Boot backend for transaction processing; 30-80 LPA for 6-10 years
- Enterprise product companies (SAP India, Oracle India, Salesforce India): 40-100 LPA for senior Java engineers
- Indian product companies (Razorpay's Java payment processing team, Freshworks backend): 30-70 LPA
Java vs other languages salary parity: at senior levels, Java engineers at product companies earn comparably to Python or Go engineers. The differentiation is domain expertise: a Java Spring Boot architect with banking domain knowledge earns a premium over a Java engineer without domain depth.
JVM internals: garbage collection and memory model
JVM internals questions for senior Java interviews:
1. JVM memory structure: Heap: where Java objects live; divided into Young Generation (Eden, Survivor spaces) and Old Generation. New objects are allocated in Eden; surviving minor GCs are promoted to Survivor spaces and eventually to Old Generation. Metaspace (Java 8+): class metadata (replaces PermGen from Java 7 and earlier). Grows dynamically; configure with -XX:MaxMetaspaceSize. Stack: per-thread; holds stack frames for method invocations; local variables and references. Native memory: used by JVM internals, off-heap data structures (NIO direct buffers).
2. Garbage collection algorithms: Serial GC: single-threaded; for single-core VMs or very small heaps. Parallel GC: multi-threaded minor and major GC; throughput-optimised; good for batch processing. G1 GC (Garbage First, default since Java 9): region-based heap; targets predictable pause times (-XX:MaxGCPauseMillis); concurrent marking with brief stop-the-world phases. ZGC (Java 11+): very low latency; concurrent (most work done while application threads run); handles terabytes of heap; sub-millisecond pauses. Shenandoah: similar to ZGC; concurrent; low pause times.
3. Java Memory Model (JMM): The JMM defines how threads interact through memory. Key concepts: Visibility: changes made by one thread may not be visible to another without synchronisation. The volatile keyword ensures visibility (all writes to a volatile variable are visible to all threads). Happens-before: if A happens-before B, A's effects are visible to B. Establishing happens-before: synchronized blocks, volatile reads/writes, Thread.start(), Thread.join(). Atomic operations: reads and writes to primitive types (except long and double on 32-bit JVMs) are atomic. Use volatile for visibility; use AtomicLong/AtomicInteger for atomic compound operations.
Java concurrency: threads, locks, and executors
Java concurrency questions:
1. synchronized vs Lock vs Atomic: synchronized: simplest; monitors a method or block; re-entrant (a thread can acquire the same lock it already holds); cannot be interrupted while waiting; no timeout. java.util.concurrent.Lock (ReentrantLock): explicit lock acquisition and release; interruptible (lockInterruptibly()); tryLock() for timeout; fairer lock acquisition (FIFO order option). Atomic classes (AtomicInteger, AtomicLong, AtomicReference): lock-free using CPU compare-and-swap (CAS) instructions; most efficient for single-variable atomic updates; no blocking.
2. Thread pools and ExecutorService: Do NOT create raw Thread objects for every task. Use ExecutorService with a thread pool: FixedThreadPool(n): n worker threads; tasks queue when all are busy. Use for CPU-bound work. CachedThreadPool: creates threads as needed; reuses idle threads; can create unbounded threads (dangerous for memory). Use for many short-lived tasks. ScheduledExecutorService: for recurring tasks (replaces Timer, which does not handle exceptions well). VirtualThreads (Java 21+): lightweight threads managed by the JVM; can create millions; ideal for I/O-bound work (replaces reactive/non-blocking frameworks like WebFlux for most use cases).
3. Common concurrency bugs: Deadlock: two threads each hold a lock the other needs. Prevention: always acquire locks in the same order; use tryLock() with timeout. Livelock: two threads keep responding to each other and neither makes progress. Starvation: a low-priority thread never gets CPU time. Race condition: two threads access shared mutable state without synchronisation; result depends on scheduling.
Practise advanced Java and Spring Boot interview questions with HireStepX's AI voice interviewer. Get scored feedback on your technical depth and how clearly you explain complex JVM and concurrency concepts. First 2 sessions free.
Practice freeSpring Boot advanced: dependency injection, auto-configuration, and Spring Data
Spring Boot advanced interview questions:
1. Spring IoC and dependency injection: IoC (Inversion of Control): the Spring container manages object creation and wiring (instead of your code creating dependencies with new). Dependency injection (DI): dependencies are injected into a class by the container, not created by the class. Three ways to inject in Spring: constructor injection (recommended; dependencies are final; easier to test), setter injection, and field injection (@Autowired on a field; least recommended because it makes testing harder and hides dependencies).
2. Spring Boot auto-configuration: Spring Boot uses @EnableAutoConfiguration (included via @SpringBootApplication) to scan the classpath and automatically configure Spring beans based on what libraries are present. Example: if spring-data-jpa and an H2 dependency are on the classpath, Spring Boot automatically configures a DataSource, EntityManagerFactory, and TransactionManager. How to understand what was auto-configured: run with --debug flag; Spring Boot prints a Conditions Evaluation Report showing which auto-configurations were applied and which were excluded and why. Override: add your own @Bean definition with the same type; Spring Boot backs off.
3. Spring Data JPA: @Entity: marks a class as a JPA entity (mapped to a database table). @Repository / JpaRepository<Entity, IdType>: Spring Data automatically generates CRUD implementations. Derived query methods: findByEmailAndStatus(email, status) generates a JPQL query from the method name without writing SQL. @Transactional: marks a method as transactional; if an exception propagates out, the transaction is rolled back. N+1 query problem: fetching a list of entities with @ManyToOne or @OneToMany relations can trigger N+1 database queries (1 for the list, then 1 per entity for the related data). Fix with @EntityGraph, JOIN FETCH in JPQL, or @BatchSize.
4. Spring Security: FilterChain: Spring Security works as a chain of servlet filters. SecurityFilterChain bean defines which endpoints require authentication and which do not. JWT authentication: stateless; the server issues a JWT on login; subsequent requests include the JWT in the Authorization header; the server validates the token without a database lookup. CSRF protection: enabled by default in Spring Security for browser clients (state-changing requests require a CSRF token); disable for REST APIs consumed only by non-browser clients.
Frequently asked questions
Explore more