Overview
This module provides comprehensive coverage of Java memory management, including JVM architecture, memory areas, garbage collection, memory leaks, and performance tuning techniques.
Learning Objectives
- Understand JVM memory architecture
- Learn about different memory areas
- Master garbage collection concepts
- Identify and prevent memory leaks
- Perform memory profiling and analysis
- Optimize memory usage
- Understand weak, soft, and phantom references
Topics Covered
18.1 JVM Architecture
18.1.1 JVM Components
- Class Loader Subsystem
- Runtime Data Areas
- Execution Engine
- Native Method Interface
- Native Method Libraries
18.1.2 Class Loader Subsystem
- Bootstrap Class Loader
- Extension Class Loader
- Application Class Loader
- Loading, Linking, Initialization
- Custom Class Loaders
18.1.3 Execution Engine
- Interpreter
- JIT (Just-In-Time) Compiler
- Garbage Collector
- Profiler
18.2 JVM Memory Structure
18.2.1 Runtime Data Areas
- Heap Memory
- Stack Memory
- Method Area
- PC Registers
- Native Method Stack
18.2.2 Heap Memory
- Young Generation
- Eden Space
- Survivor Spaces (S0, S1)
- Old Generation (Tenured)
- Object Storage
- Garbage Collection Target
18.2.3 Stack Memory
- Thread-Specific
- Method Frames
- Local Variables
- Method Call Stack
- Stack Overflow
18.2.4 Method Area (Metaspace)
- Class Metadata
- Static Variables
- Constant Pool
- Method Data
- PermGen (Old) vs Metaspace (Java 8+)
18.2.5 PC Register
- Program Counter
- Thread-Specific
- Next Instruction
18.2.6 Native Method Stack
- Native Method Calls
- JNI Operations
- C/C++ Integration
18.3 Object Creation and Memory Allocation
18.3.1 Object Creation Process
- Class Loading
- Memory Allocation
- Initialization
- Reference Assignment
18.3.2 Memory Allocation
- Eden Space Allocation
- TLAB (Thread-Local Allocation Buffer)
- Fast Path Allocation
- Slow Path Allocation
18.3.3 Object Memory Layout
- Object Header
- Mark Word
- Class Pointer
- Instance Data
- Padding
- Memory Alignment
18.3.4 String Pool
- String Interning
- String Constant Pool
- Memory Optimization
- intern() Method
18.4 Garbage Collection
18.4.1 Introduction to GC
- Automatic Memory Management
- Mark and Sweep
- Generational Hypothesis
- GC Roots
- Reachability
18.4.2 GC Roots
- Local Variables
- Static Variables
- Active Threads
- JNI References
- Reachability Analysis
18.4.3 Generational GC
- Young Generation Collection
- Old Generation Collection
- Minor GC
- Major GC
- Full GC
18.4.4 GC Algorithms
- Mark-Sweep
- Mark-Sweep-Compact
- Mark-Copy
- Reference Counting (Not Used in Java)
18.4.5 Young Generation GC
- Eden and Survivor Spaces
- Copy Algorithm
- Age Threshold
- Promotion to Old Gen
18.4.6 Old Generation GC
- Mark-Sweep-Compact
- Longer Pauses
- Less Frequent
- Full Collection
18.5 Garbage Collectors
18.5.1 Serial GC
- Single-Threaded
- Stop-The-World
- Small Applications
- -XX:+UseSerialGC
18.5.2 Parallel GC (Throughput Collector)
- Multi-Threaded
- Stop-The-World
- High Throughput
- -XX:+UseParallelGC
18.5.3 CMS (Concurrent Mark Sweep)
- Low Latency
- Concurrent Phases
- Fragmentation Issues
- Deprecated in Java 9
18.5.4 G1 GC (Garbage First)
- Default since Java 9
- Region-Based
- Predictable Pauses
- Large Heaps
- -XX:+UseG1GC
18.5.5 ZGC (Z Garbage Collector)
- Ultra-Low Latency
- Concurrent GC
- Scalable
- Java 11+
- -XX:+UseZGC
18.5.6 Shenandoah GC
- Low Pause Times
- Concurrent Compaction
- Java 12+
- -XX:+UseShenandoahGC
18.5.7 Epsilon GC
- No-Op Collector
- Testing/Benchmarking
- Short-Lived Apps
- -XX:+UseEpsilonGC
18.6 GC Tuning
18.6.1 JVM Memory Options
- -Xms (Initial Heap)
- -Xmx (Maximum Heap)
- -Xmn (Young Generation)
- -XX:NewRatio
- -XX:SurvivorRatio
18.6.2 GC Logging
- -Xlog:gc (Java 9+)
- GC Log Analysis
- Pause Times
- Throughput Metrics
18.6.3 Tuning Goals
- Throughput
- Latency
- Footprint
- Trade-offs
18.6.4 Common GC Parameters
- -XX:MaxGCPauseMillis
- -XX:GCTimeRatio
- -XX:ParallelGCThreads
- -XX:ConcGCThreads
18.7 Memory Leaks
18.7.1 Understanding Memory Leaks
- Unintentional Object Retention
- Growing Memory Usage
- OutOfMemoryError
- Performance Degradation
18.7.2 Common Causes
- Static Collections
- Listeners Not Removed
- Unclosed Resources
- ThreadLocal Variables
- Inner Class References
- Caching Issues
18.7.3 Detecting Memory Leaks
- Heap Dumps
- Memory Profilers
- GC Logs
- Monitoring Tools
18.7.4 Prevention Strategies
- Proper Resource Management
- WeakHashMap Usage
- Listener Cleanup
- ThreadLocal Cleanup
- Bounded Caches
18.8 Reference Types
18.8.1 Strong References
- Default Reference Type
- GC Behavior
- Object Retention
- Normal Variables
18.8.2 Soft References
- SoftReference
- Memory-Sensitive Caches
- GC Behavior
- Before OutOfMemoryError
18.8.3 Weak References
- WeakReference
- WeakHashMap
- GC Behavior
- Next GC Cycle
18.8.4 Phantom References
- PhantomReference
- Finalization Alternative
- Reference Queue
- Cleanup Actions
18.8.5 Reference Queues
- ReferenceQueue
- Notification Mechanism
- Cleanup Tasks
- Polling/Blocking
18.9 Finalization
18.9.1 finalize() Method
- Object Cleanup
- Before GC
- Deprecated (Java 9+)
- Problems
18.9.2 Finalization Issues
- Unpredictable Timing
- Performance Impact
- Resurrection
- Better Alternatives
18.9.3 Alternatives to finalize()
- try-with-resources
- Cleaner API (Java 9+)
- Explicit Cleanup Methods
- PhantomReference
18.10 Cleaner API (Java 9+)
18.10.1 Understanding Cleaner
- Finalization Alternative
- Explicit Registration
- Cleaner Thread
- Resource Management
18.10.2 Using Cleaner
- Cleaner.create()
- register() Method
- Cleanable Interface
- Best Practices
18.11 Memory Profiling
18.11.1 Profiling Tools
- JVisualVM
- JConsole
- Java Mission Control
- YourKit
- JProfiler
- Eclipse MAT
18.11.2 Heap Dumps
- Creating Heap Dumps
- -XX:+HeapDumpOnOutOfMemoryError
- jmap Command
- Analyzing Dumps
18.11.3 Memory Analysis
- Object Retention
- Dominator Tree
- Shallow vs Retained Size
- Leak Suspects
18.11.4 Thread Dumps
- Thread States
- Stack Traces
- Deadlock Detection
- jstack Command
18.12 Memory Optimization
18.12.1 Object Pooling
- Reusing Objects
- Pool Implementation
- When to Use
- Trade-offs
18.12.2 Immutable Objects
- Memory Sharing
- Thread Safety
- String Pool Example
- Benefits
18.12.3 Lazy Initialization
- On-Demand Creation
- Memory Savings
- Double-Checked Locking
- Holder Pattern
18.12.4 Primitive Types vs Wrappers
- Memory Overhead
- Auto-boxing Cost
- Performance Impact
- When to Use Each
18.12.5 Collection Sizing
- Initial Capacity
- Load Factor
- Resizing Cost
- Memory Pre-allocation
18.12.6 String Optimization
- StringBuilder Usage
- String Concatenation
- String Deduplication
- Compact Strings (Java 9+)
18.13 Memory Best Practices
18.13.1 Design Guidelines
- Minimize Object Creation
- Favor Immutability
- Use Primitives When Possible
- Proper Collection Sizing
- Resource Cleanup
18.13.2 Coding Practices
- Avoid Premature Optimization
- Profile Before Optimizing
- Use try-with-resources
- Clear Collections
- Avoid String Concatenation in Loops
18.13.3 Architecture Patterns
- Object Pooling
- Flyweight Pattern
- Singleton Pattern
- Cache Strategies
18.14 OutOfMemoryError
18.14.1 Types of OOME
- Heap Space
- Metaspace/PermGen
- GC Overhead Limit
- Unable to Create Native Thread
- Direct Buffer Memory
18.14.2 Diagnosis
- Heap Dumps
- GC Logs
- Error Messages
- System Resources
18.14.3 Resolution
- Increase Heap Size
- Fix Memory Leaks
- Optimize Code
- Review Architecture
18.15 Stack Memory Management
18.15.1 Stack Overflow
- Causes
- Recursive Calls
- Deep Call Stacks
- Stack Size (-Xss)
18.15.2 Stack vs Heap
- Allocation Speed
- Lifetime
- Size Limits
- Thread Safety
18.16 Native Memory
18.16.1 Off-Heap Memory
- Direct ByteBuffers
- Native Allocations
- Memory-Mapped Files
- JNI
18.16.2 Direct Memory
- DirectByteBuffer
- Advantages
- Disadvantages
- -XX:MaxDirectMemorySize
18.17 Memory Monitoring
18.17.1 JMX (Java Management Extensions)
- MemoryMXBean
- GarbageCollectorMXBean
- Runtime Monitoring
- Memory Pools
18.17.2 Runtime Class
- totalMemory()
- freeMemory()
- maxMemory()
- gc()
18.17.3 Management Factory
- Memory Usage
- GC Statistics
- Thread Information
- Class Loading
18.18 Advanced Topics
18.18.1 Compressed Oops
- Object Pointer Compression
- Heap Size < 32GB
- Memory Savings
- -XX:+UseCompressedOops
18.18.2 Escape Analysis
- JIT Optimization
- Stack Allocation
- Scalar Replacement
- Lock Elision
18.18.3 NUMA Awareness
- Non-Uniform Memory Access
- Multi-Socket Machines
- -XX:+UseNUMA
Hands-on Exercises
- Analyze heap dumps
- Create and fix memory leaks
- Tune GC parameters
- Implement different reference types
- Use memory profilers
- Optimize object creation
- Implement object pooling
- Monitor memory usage with JMX
- Analyze GC logs
- Create OutOfMemoryError scenarios
- Implement Cleaner API
- Performance tuning exercises
Key Takeaways
- JVM manages memory automatically
- Generational GC improves performance
- Different GC collectors for different needs
- Memory leaks can occur in Java
- Proper resource management is crucial
- Reference types provide flexibility
- Profiling identifies memory issues
- Tuning requires understanding trade-offs
Common Mistakes to Avoid
- Ignoring resource cleanup
- Static collection accumulation
- Not removing listeners
- Overusing finalize()
- Premature optimization
- Wrong GC choice
- Not monitoring memory
- Ignoring memory leaks
Real-World Applications
- Enterprise applications
- High-performance systems
- Long-running services
- Memory-constrained environments
- Big data processing
- Real-time systems
- Microservices
Additional Resources
- Java Performance: The Definitive Guide
- Java Performance Tuning
- GC Handbook
- JVM Specification
- Memory Profiling Tools Documentation
Assessment
- Quiz on memory management
- Practical: Memory leak detection
- GC tuning exercises
- Heap dump analysis
- Performance optimization challenges
Previous Module
Module 17: Advanced Java Features