JVM Internals & Garbage Collection
The Java Virtual Machine (JVM) is the cornerstone of Java’s platform independence. Understanding its internals is crucial for writing high-performance Java applications.JVM Architecture
Overview
The JVM is a specification that defines how Java bytecode should be executed. Different vendors provide their own implementations (HotSpot, OpenJ9, GraalVM, etc.).
JVM Components
Class Loader Subsystem
Class Loader Subsystem
Responsible for loading class files into the JVM:Three phases:
- Loading: Reads .class files and creates binary data
- Linking: Verification, preparation, and resolution
- Initialization: Executes static initializers and static blocks
Runtime Data Areas
Runtime Data Areas
Memory areas used during program execution:
- Heap
- Stack
- Method Area
- PC Register
- Shared among all threads
- Stores objects and instance variables
- Garbage collected
- Divided into Young and Old generations
Execution Engine
Execution Engine
Executes bytecode through:
- Interpreter: Executes bytecode line by line
- JIT Compiler: Compiles frequently used bytecode to native code
- Garbage Collector: Manages memory automatically
Java Bytecode
Understanding Bytecode
Java bytecode is the instruction set of the JVM. Understanding bytecode helps in performance optimization and debugging.
Common Bytecode Instructions
- Stack Operations
- Arithmetic
- Method Invocation
Memory Management
Heap Structure
Memory Configuration
Garbage Collection
GC Algorithms
- Serial GC
- Parallel GC
- CMS (Concurrent Mark Sweep)
- G1 (Garbage First)
- ZGC / Shenandoah
Characteristics:Use Case: Single-processor machines or small applications
- Single-threaded
- Stop-the-world pauses
- Suitable for small heaps
GC Process
Marking Phase
Identifies live objects by following references from GC roots:
- Thread stacks
- Static variables
- JNI references
Monitoring GC
Performance Tuning
JIT Compilation
The JIT compiler optimizes frequently executed code (“hot spots”) by compiling it to native machine code.
Common Performance Issues
Memory Leaks
Memory Leaks
Common Causes:
- Unclosed resources
- Static collections
- Thread locals
- Event listeners not removed
High GC Overhead
High GC Overhead
Symptoms:
- Frequent GC cycles
- Long pause times
- Low throughput
- Increase heap size
- Tune GC algorithm
- Reduce object creation
- Use object pools for frequently created objects
Class Loading Issues
Class Loading Issues
Problems:
- ClassNotFoundException
- NoClassDefFoundError
- Class version conflicts
Profiling Tools
jstat
Monitor JVM statistics
jmap
Memory map and heap dump
jstack
Thread dump for deadlock detection
VisualVM
All-in-one profiling tool with GUI
Best Practices
Choose Right GC
- G1GC for most applications
- ZGC/Shenandoah for low-latency requirements
- Parallel GC for batch processing
Monitor and Profile
- Enable GC logging in production
- Use APM tools (New Relic, Dynatrace)
- Regular heap dump analysis
Optimize Memory Usage
- Reuse objects when possible
- Use primitive types over wrappers
- Close resources properly (try-with-resources)
Related Topics
Java Fundamentals
Learn Java basics
Concurrency
Master multithreading
Spring Framework
Enterprise development