Skip to content

Commit c46f59a

Browse files
Add README.md for Module 10: JVM & Memory Management covering overview, learning objectives, JVM architecture, garbage collection, memory monitoring, performance optimization, and practice exercises
1 parent 28fe671 commit c46f59a

File tree

1 file changed

+340
-0
lines changed

1 file changed

+340
-0
lines changed

module10-jvm/README.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
# Module 10: JVM & Memory Management
2+
3+
## 📋 Overview
4+
Understand JVM internals and memory management for optimizing Spring application performance.
5+
6+
## 🎯 Learning Objectives
7+
- Understand JVM architecture and memory areas
8+
- Master garbage collection concepts and tuning
9+
- Apply memory optimization techniques
10+
- Monitor and profile Spring applications
11+
12+
## 📚 JVM Architecture
13+
14+
### Memory Areas
15+
```java
16+
public class JVMMemoryExample {
17+
18+
// Method Area (Metaspace in Java 8+)
19+
// - Class metadata, constant pool, static variables
20+
private static final String CONSTANT = "This goes to Method Area";
21+
private static int staticCounter = 0;
22+
23+
// Heap Memory
24+
// - Object instances, instance variables
25+
private String instanceVariable; // Reference in stack, object in heap
26+
private List<String> dataList = new ArrayList<>(); // Both reference and ArrayList object in heap
27+
28+
public void demonstrateMemoryUsage() {
29+
// Stack Memory
30+
// - Local variables, method parameters, return addresses
31+
int localInt = 42; // Primitive in stack
32+
String localString = "Local"; // Reference in stack, object in heap
33+
User localUser = new User(); // Reference in stack, User object in heap
34+
35+
// Method calls create stack frames
36+
processData(localString);
37+
}
38+
39+
private void processData(String data) {
40+
// New stack frame created
41+
char[] charArray = data.toCharArray(); // Array object in heap
42+
43+
// When method returns, stack frame is removed
44+
}
45+
46+
// PC Register and Native Method Stack are managed by JVM
47+
}
48+
```
49+
50+
### Garbage Collection
51+
```java
52+
@Component
53+
public class MemoryOptimizationService {
54+
55+
// Avoid memory leaks
56+
private final Map<String, WeakReference<CachedData>> cache = new ConcurrentHashMap<>();
57+
58+
public void demonstrateGCBehavior() {
59+
List<String> data = new ArrayList<>();
60+
61+
// Young Generation objects
62+
for (int i = 0; i < 1000; i++) {
63+
data.add("String " + i); // Short-lived objects
64+
}
65+
66+
// Suggest GC (not guaranteed)
67+
System.gc();
68+
69+
// Long-lived objects move to Old Generation
70+
staticCache.putAll(createLongLivedData());
71+
}
72+
73+
private static final Map<String, Object> staticCache = new ConcurrentHashMap<>();
74+
75+
// Memory-efficient caching
76+
public CachedData getCachedData(String key) {
77+
WeakReference<CachedData> ref = cache.get(key);
78+
if (ref != null) {
79+
CachedData data = ref.get();
80+
if (data != null) {
81+
return data;
82+
} else {
83+
// Object was garbage collected
84+
cache.remove(key);
85+
}
86+
}
87+
88+
// Create new cached data
89+
CachedData newData = loadData(key);
90+
cache.put(key, new WeakReference<>(newData));
91+
return newData;
92+
}
93+
94+
private Map<String, Object> createLongLivedData() {
95+
return Map.of("config1", "value1", "config2", "value2");
96+
}
97+
98+
private CachedData loadData(String key) {
99+
return new CachedData(key);
100+
}
101+
}
102+
```
103+
104+
### Memory Monitoring
105+
```java
106+
@Service
107+
public class MemoryMonitoringService {
108+
private final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
109+
private final List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
110+
111+
@Scheduled(fixedRate = 60000) // Every minute
112+
public void logMemoryUsage() {
113+
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
114+
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
115+
116+
log.info("Heap Memory - Used: {} MB, Max: {} MB, Usage: {}%",
117+
heapUsage.getUsed() / 1024 / 1024,
118+
heapUsage.getMax() / 1024 / 1024,
119+
(heapUsage.getUsed() * 100.0) / heapUsage.getMax());
120+
121+
log.info("Non-Heap Memory - Used: {} MB, Max: {} MB",
122+
nonHeapUsage.getUsed() / 1024 / 1024,
123+
nonHeapUsage.getMax() / 1024 / 1024);
124+
125+
for (GarbageCollectorMXBean gcBean : gcBeans) {
126+
log.info("GC {} - Collections: {}, Time: {} ms",
127+
gcBean.getName(),
128+
gcBean.getCollectionCount(),
129+
gcBean.getCollectionTime());
130+
}
131+
}
132+
133+
public MemoryInfo getMemoryInfo() {
134+
Runtime runtime = Runtime.getRuntime();
135+
return MemoryInfo.builder()
136+
.totalMemory(runtime.totalMemory())
137+
.freeMemory(runtime.freeMemory())
138+
.maxMemory(runtime.maxMemory())
139+
.usedMemory(runtime.totalMemory() - runtime.freeMemory())
140+
.build();
141+
}
142+
}
143+
```
144+
145+
## ⚡ Performance Optimization
146+
147+
### JVM Tuning Parameters
148+
```bash
149+
# Common JVM tuning parameters for Spring applications
150+
151+
# Heap size settings
152+
-Xms2g # Initial heap size
153+
-Xmx4g # Maximum heap size
154+
-XX:NewRatio=3 # Old/Young generation ratio
155+
156+
# Garbage Collection
157+
-XX:+UseG1GC # Use G1 garbage collector
158+
-XX:MaxGCPauseMillis=200 # Target pause time
159+
-XX:G1HeapRegionSize=16m # G1 region size
160+
161+
# Memory management
162+
-XX:+UseStringDeduplication # Deduplicate strings
163+
-XX:+UseCompressedOops # Compress object pointers
164+
165+
# Monitoring and debugging
166+
-XX:+PrintGC # Print GC info
167+
-XX:+PrintGCDetails # Detailed GC info
168+
-XX:+HeapDumpOnOutOfMemoryError # Dump heap on OOM
169+
-XX:HeapDumpPath=/tmp/ # Heap dump location
170+
171+
# JIT compilation
172+
-XX:+TieredCompilation # Enable tiered compilation
173+
-XX:CompileThreshold=10000 # Method compilation threshold
174+
```
175+
176+
### Memory Optimization Techniques
177+
```java
178+
@Service
179+
public class OptimizedDataProcessor {
180+
181+
// Use primitive collections when possible
182+
private final TIntObjectHashMap<String> primitiveMap = new TIntObjectHashMap<>();
183+
184+
// Object pooling for expensive objects
185+
private final ObjectPool<ExpensiveObject> objectPool = new GenericObjectPool<>(
186+
new ExpensiveObjectFactory(),
187+
new GenericObjectPoolConfig<>()
188+
);
189+
190+
// Efficient string handling
191+
public void processLargeText(String text) {
192+
// Use StringBuilder for string concatenation
193+
StringBuilder result = new StringBuilder(text.length() * 2);
194+
195+
// Process in chunks to avoid large temporary objects
196+
int chunkSize = 1000;
197+
for (int i = 0; i < text.length(); i += chunkSize) {
198+
int end = Math.min(i + chunkSize, text.length());
199+
String chunk = text.substring(i, end);
200+
result.append(processChunk(chunk));
201+
}
202+
}
203+
204+
// Use streams efficiently
205+
public List<ProcessedData> processDataStream(List<RawData> input) {
206+
return input.stream()
207+
.filter(this::isValid)
208+
.map(this::transform)
209+
.collect(Collectors.toCollection(
210+
() -> new ArrayList<>(input.size()) // Pre-size collection
211+
));
212+
}
213+
214+
// Minimize object creation in loops
215+
public void optimizedLoop(List<String> items) {
216+
StringBuilder buffer = new StringBuilder(); // Reuse
217+
218+
for (String item : items) {
219+
buffer.setLength(0); // Reset instead of creating new
220+
buffer.append("Processed: ").append(item);
221+
processItem(buffer.toString());
222+
}
223+
}
224+
225+
private String processChunk(String chunk) {
226+
return chunk.toUpperCase();
227+
}
228+
229+
private boolean isValid(RawData data) {
230+
return data != null;
231+
}
232+
233+
private ProcessedData transform(RawData data) {
234+
return new ProcessedData(data);
235+
}
236+
237+
private void processItem(String item) {
238+
// Process item
239+
}
240+
}
241+
```
242+
243+
## 🌸 Spring Boot Memory Optimization
244+
245+
### Configuration for Production
246+
```yaml
247+
# application-prod.yml
248+
spring:
249+
jpa:
250+
hibernate:
251+
ddl-auto: none
252+
show-sql: false
253+
properties:
254+
hibernate:
255+
# Enable batch processing
256+
jdbc.batch_size: 25
257+
order_inserts: true
258+
order_updates: true
259+
# Use connection pooling
260+
connection.provider_class: com.zaxxer.hikari.hibernate.HikariConnectionProvider
261+
262+
management:
263+
endpoints:
264+
web:
265+
exposure:
266+
include: health,info,metrics,prometheus
267+
endpoint:
268+
health:
269+
show-details: when-authorized
270+
metrics:
271+
enabled: true
272+
273+
# Connection pool optimization
274+
spring.datasource.hikari:
275+
maximum-pool-size: 20
276+
minimum-idle: 5
277+
connection-timeout: 30000
278+
idle-timeout: 600000
279+
max-lifetime: 1800000
280+
```
281+
282+
### Monitoring with Actuator
283+
```java
284+
@Component
285+
public class CustomMetrics {
286+
private final MeterRegistry meterRegistry;
287+
private final Counter processedItemsCounter;
288+
private final Timer processingTimer;
289+
private final Gauge memoryGauge;
290+
291+
public CustomMetrics(MeterRegistry meterRegistry) {
292+
this.meterRegistry = meterRegistry;
293+
this.processedItemsCounter = Counter.builder("processed.items")
294+
.description("Number of processed items")
295+
.register(meterRegistry);
296+
297+
this.processingTimer = Timer.builder("processing.time")
298+
.description("Time spent processing")
299+
.register(meterRegistry);
300+
301+
this.memoryGauge = Gauge.builder("memory.used.percentage")
302+
.description("Memory usage percentage")
303+
.register(meterRegistry, this, CustomMetrics::getMemoryUsagePercentage);
304+
}
305+
306+
public void recordProcessedItem() {
307+
processedItemsCounter.increment();
308+
}
309+
310+
public void recordProcessingTime(Duration duration) {
311+
processingTimer.record(duration);
312+
}
313+
314+
private double getMemoryUsagePercentage() {
315+
Runtime runtime = Runtime.getRuntime();
316+
long used = runtime.totalMemory() - runtime.freeMemory();
317+
long max = runtime.maxMemory();
318+
return (double) used / max * 100;
319+
}
320+
}
321+
```
322+
323+
## 🏃‍♂️ Practice Exercises
324+
325+
1. Profile a Spring application and identify memory hotspots
326+
2. Implement object pooling for expensive resources
327+
3. Optimize database query performance with JPA
328+
4. Create custom metrics for application monitoring
329+
330+
## 📊 GC Algorithm Comparison
331+
332+
| Algorithm | Use Case | Pros | Cons |
333+
|-----------|----------|------|------|
334+
| **Serial GC** | Small applications | Simple, low overhead | Single-threaded |
335+
| **Parallel GC** | Throughput-focused | Multi-threaded | Longer pause times |
336+
| **G1 GC** | Large heaps, low latency | Predictable pauses | More complex |
337+
| **ZGC/Shenandoah** | Very large heaps | Ultra-low latency | Experimental |
338+
339+
---
340+
**Next Module**: [Dependency Injection Concepts](../module11-di/README.md)

0 commit comments

Comments
 (0)