Questions d'entretien Java Senior
1. Comment fonctionne le Garbage Collector de la JVM ?
Le GC libère automatiquement la mémoire des objets non références. La heap est divisee en Young Génération (Eden + Survivor spaces) et Old Génération. Les objets sont crees dans Eden. Les collections "minor" (Young GC) sont rapides et fréquentes. Les objets survivant à plusieurs cycles sont promus en Old Gen. Les collections "major" (Full GC) sont plus lentes. Collecteurs modernes : G1 (défaut depuis Java 9, bon équilibre pause/throughput), ZGC (pauses < 1ms, idéal pour les grandes heaps), Shenandoah (pauses faibles, RedHat).
2. Expliquez les Virtual Threads (Project Loom) de Java 21.
Les Virtual Threads sont des threads legers gérés par la JVM plutôt que par l'OS. Ils permettent de créer des millions de threads concurrents (contre quelques milliers de threads OS). L'API est identique aux threads classiques (Thread.ofVirtual().start()). Chaque virtual thread est monte sur un carrier thread (thread OS) et peut être demonte pendant les opérations bloquantes (I/O). C'est revolutionnaire pour les serveurs qui gagnent en throughput sans recourir aux callbacks asynchrones complexes.
3. Qu'est-ce que le pattern Reactor et la programmation réactive en Java ?
La programmation réactive gere des flux de données asynchrones avec backpressure (le consommateur contrôle le rythme). En Java : Project Reactor (Mono et Flux, utilise par Spring WebFlux), RxJava (Observable, Single, Completable). Opérateurs : map, flatMap, filter, zip, retry, buffer, window. La programmation réactive est idéale pour les applications I/O-bound avec beaucoup de connexions simultanées. Cependant, avec les Virtual Threads de Java 21, la programmation impérative classique redevient competitiv.
4. Expliquez les Records, Sealed Classes et Pattern Matching de Java moderne.
Les Records (Java 16) sont des classes de données immutables avec equals/hashCode/toString generes : record Point(int x, int y) {}. Les Sealed Classes (Java 17) restreignent la hiérarchie : sealed interface Shape permits Circle, Rectangle {}. Le Pattern Matching pour instanceof (Java 16) : if (shape instanceof Circle c) { c.radius(); }. Le Pattern Matching pour switch (Java 21) combine tout : switch (shape) { case Circle c -> ...; case Rectangle r -> ...; }. Ces features permettent la modélisation de domaine avec des types algebriques.
5. Comment concevoir une application thread-safe en Java ?
Stratégies : immutabilité (records, objets immutables — aucune synchronisation nécessaire), confinement au thread (ThreadLocal), classes thread-safe du JDK (ConcurrentHashMap, AtomicInteger, CopyOnWriteArrayList), synchronized (moniteur intrinseque, granularité objet), ReentrantLock (plus flexible, tryLock, fairness), StampedLock (optimiste, pour les cas read-heavy). Évitez les synchronized sur des méthodes entières. Préférez les structures immutables et les classes concurrent du JDK.
6. Expliquez les design patterns les plus utiles en Java.
Strategy : encapsuler des algorithmes interchangeables (Comparator en Java). Builder : construction d'objets complexes étape par étape (Pattern Lombok @Builder). Factory : délégation de la création d'objets. Observer : notification d'événements (PropertyChangeListener, réactive streams). Decorator : ajouter des comportements dynamiquement (I/O streams : BufferedInputStream(new FileInputStream(...))). Proxy : contrôle d'accès (Spring AOP, Hibernate lazy loading). Template Method : définir le squelette d'un algorithme (AbstractList).
7. Comment diagnostiquer un problème de performance en Java ?
Outils : JVisualVM ou JConsole (monitoring en temps réel, heap, threads), JFR (Java Flight Recorder, profiling faible overhead), JMC (Java Mission Control, analyse des enregistrements JFR), async-profiler (profiling CPU et allocation, flame graphs), jmap (heap dump), jstack (thread dump pour les deadlocks). Métriques clés : CPU usage, heap usage, GC pause time, thread count, contention des locks. Prenez un thread dump si l'application semble "bloquee".
8. Qu'est-ce que le classloading en Java et comment fonctionne-t-il ?
Le ClassLoader charge les classes bytecode en mémoire. Hiérarchie : Bootstrap ClassLoader (classes core Java), Platform ClassLoader (modules Java), Application ClassLoader (classpath de l'application). Le mécanisme de délégation parente : un ClassLoader demande d'abord à son parent de charger la classe avant de le faire lui-meme. Cela evite les conflits. Les serveurs d'applications (Tomcat) et les frameworks de modules (OSGi) utilisent des ClassLoaders personnalisés pour l'isolation des applications.
9. Expliquez le système de modules Java (JPMS).
Le Java Platform Module System (Project Jigsaw, Java 9) decoupe la plateforme et les applications en modules. Un module est défini par module-info.java : requires (dépendances), exports (packages publics), opens (packages ouverts à la réflexion), provides/uses (services). Avantages : encapsulation forte (seuls les packages exportes sont accessibles), dépendances explicites, images runtime minimales (jlink). En pratique, beaucoup de projets n'utilisent pas encore les modules, mais le JDK lui-meme est modularise.
10. Comment optimiser une application Spring Boot en production ?
Configuration : activez la compilation native (GraalVM Native Image pour des demarrages ultra-rapides), Spring AOT (compilation ahead-of-time), Virtual Threads (spring.threads.virtual.enabled=true en Java 21+). Performance : connection pooling (HikariCP configure correctement), cache (Spring Cache avec Caffeine ou Redis), compression gzip des réponses, profils adaptes (logging minimal en prod). Monitoring : Spring Boot Actuator + Prometheus + Grafana pour les métriques, Micrometer tracing pour le tracing distribue.