# Jvm Performance

> JVM performance tuning including garbage collection algorithms, GC selection, heap analysis, profiling tools, and cloud-native considerations. Use when diagnosing performance issues or tuning JVM parameters.

- Skill: `iceflower/jvm-performance` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add iceflower/jvm-performance`
- Raw SKILL.md: https://api.skillmd.com/api/skills/iceflower/jvm-performance/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: MIT
- Author: iceflower (https://skillmd.com/u/iceflower)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/iceflower/jvm-performance

---


# JVM Performance Optimization

Java Virtual Machine performance tuning, garbage collection, and profiling techniques. Use when diagnosing performance issues, tuning JVM parameters, or optimizing Java applications.

> **Note**: This document synthesizes JVM performance concepts from various sources including Oracle documentation, JVM specifications, and community best practices.

## Performance Trade-offs

JVM tuning involves inherent trade-offs. Improving one metric often impacts another.

| Metric      | Description                       |
|-------------|-----------------------------------|
| Throughput  | Work units per time period        |
| Latency     | Time to complete single operation |
| Capacity    | Concurrent work units supported   |
| Utilization | Resource usage percentage         |
| Efficiency  | Throughput per resource unit      |
| Scalability | Performance under increasing load |
| Degradation | Performance decline over time     |

## 2. Garbage Collection Algorithms

> See [references/gc-tuning.md](references/gc-tuning.md) for detailed GC algorithms (mark-and-sweep, generational collection, STW pauses), JVM tuning parameters, memory analysis, and JIT compilation.

---

## 3. Garbage Collectors

> **See [references/garbage-collectors.md](references/garbage-collectors.md) for detailed information on:**
>
> - Serial GC, Parallel GC, G1 GC
> - ZGC (Z Garbage Collector)
> - Shenandoah

---

## 4. GC Selection Guide

| Heap Size   | Latency Requirement       | Recommended GC       |
|-------------|---------------------------|----------------------|
| < 100MB     | Any                       | Serial               |
| < 4GB       | Throughput priority       | Parallel             |
| 4GB - 32GB  | Balanced                  | G1                   |
| > 32GB      | Low latency               | ZGC/Shenandoah       |
| Any         | Ultra-low latency (< 1ms) | ZGC/Shenandoah       |

---

## 5. Performance Analysis Approach

### Systematic Process

1. Define performance goals with specific metrics
2. Measure baseline performance
3. Identify bottlenecks through profiling
4. Make targeted changes
5. Verify improvement with measurements
6. Document findings

### Measurement Principles

- **Statistical significance**: Multiple runs required
- **Control environment**: Same hardware, data, load
- **Measure before and after**: Quantify change impact
- **Non-normal distributions**: Use percentiles, not just means

---

## 7. Profiling Tools

### JDK Flight Recorder (JFR)

Low-overhead production profiling.

```bash
# Start recording
jcmd <pid> JFR.start name=profile duration=60s filename=recording.jfr

# Or via JVM args
-XX:StartFlightRecording=duration=60s,filename=recording.jfr
```

**Events**:

- CPU usage
- Memory allocation
- GC events
- Thread events
- Method profiling

### Java Mission Control (JMC)

GUI for JFR analysis.

**Key Views**:

- Event browser
- Thread analysis
- Memory analysis
- Code profiling

### async-profiler

Low-overhead sampling profiler.

```bash
# CPU profiling
./profiler.sh -d 60 -f cpu.html <pid>

# Allocation profiling
./profiler.sh -d 60 -e alloc -f alloc.html <pid>
```

### JMX Monitoring

```bash
# Enable remote JMX
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
```

---

## 8. Common Performance Mistakes

### Optimizing Without Measurement

Making changes based on assumptions rather than data.

**Warning signs**:

- Complex code for assumed performance
- No profiling data
- "It feels faster"

### Copy-Paste Tuning

Applying JVM flags without understanding their impact.

**Warning signs**:

- Copy-paste JVM flags from blogs
- Using outdated tuning advice
- Ignoring workload characteristics

### Flawed Microbenchmarks

Microbenchmarks can produce misleading results.

**Common issues**:

- JIT compilation effects
- Dead code elimination
- Warmup not considered

**Use JMH for microbenchmarks**:

```java
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(1)
public class MyBenchmark {
    
    @Benchmark
    public void testMethod() {
        // benchmark code
    }
}
```

### Ignoring Tail Latency

Average latency can hide problematic outliers.

**Wrong**: Average is 50ms
**Right**: P99 is 500ms, indicates tail latency problem

---

## 9. Virtual Threads (Java 21+)

### Benefits

- Lightweight (millions possible)
- No thread pool management
- Simpler async code

### When to Use

**Good fit**:

- I/O-bound workloads
- Many concurrent tasks
- Blocking APIs

**Not good fit**:

- CPU-bound tasks
- Synchronized blocks (pins carrier thread)
- Thread-local heavy code

### Implementation

```java
// Create virtual thread
Thread.startVirtualThread(() -> {
    // Task code
});

// ExecutorService with virtual threads
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}
```

### Pinning Issues

**Pinning causes**: Carrier thread blocked, reducing throughput.

**Avoid**:

- `synchronized` blocks/methods
- Native methods that block

**Fix**:

```java
// Replace synchronized with ReentrantLock
// Before
synchronized(lock) { ... }

// After
private final ReentrantLock lock = new ReentrantLock();
lock.lock();
try { ... } finally { lock.unlock(); }
```

---

## 10. Cloud-Native Considerations

### Container Memory Limits

```bash
# JVM respects container limits (Java 10+)
-XX:+UseContainerSupport

# Limit JVM heap to leave room for off-heap
# Rule: Heap = Container Memory * 0.75 - Off-heap estimate
-Xmx6g  # In 8GB container with ~1GB off-heap
```

### Startup Optimization

```bash
# Class Data Sharing
java -Xshare:dump
-XX:+UseSharedSpaces

# AOT compilation (GraalVM)
native-image -jar app.jar

# CDS with dynamic archive
-XX:ArchiveClassesAtExit=app.jsa
-XX:SharedArchiveFile=app.jsa
```

### Observability Stack

```text
┌─────────────┐
│ Application │
│   (JVM)     │
└──────┬──────┘
       │
       ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Micrometer  │────▶│ Prometheus  │────▶│  Grafana    │
│  (metrics)  │     │  (storage)  │     │ (dashboard) │
└─────────────┘     └─────────────┘     └─────────────┘
       │
       ▼
┌─────────────┐     ┌─────────────┐
│OpenTelemetry│────▶│    Jaeger   │
│  (tracing)  │     │   (traces)  │
└─────────────┘     └─────────────┘
```

---

## 11. Performance Troubleshooting Checklist

### High CPU Usage

1. Profile with async-profiler
2. Check for GC overhead (`jstat -gcutil`)
3. Look for busy loops
4. Check for excessive logging

### High Memory Usage

1. Check heap usage (`jcmd GC.heap_info`)
2. Look for memory leaks (heap dump)
3. Analyze GC logs
4. Check Metaspace for class leaks

### Long GC Pauses

1. Check GC logs (`-Xlog:gc*`)
2. Analyze pause times vs goals
3. Consider different GC algorithm
4. Check for heap sizing issues

### Slow Startup

1. Profile with JFR
2. Check class loading (`-Xlog:class+load`)
3. Consider CDS or AOT
4. Reduce classpath scanning

---

## JVM Flags Quick Reference

```bash
# Essential logging
-Xlog:gc*:file=gc.log:time,uptime,level,tags

# Memory
-Xms4g -Xmx4g
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m

# G1 GC
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

# ZGC (Java 15+)
-XX:+UseZGC
-XX:ZCollectionInterval=0

# Flight Recorder
-XX:StartFlightRecording=duration=60s,filename=rec.jfr

# Heap dump on OOM
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/heap.hprof
```

---

## Related Skills

- **spring-framework**: Actuator, Micrometer setup, Spring-specific debugging
- **k8s-workflow**: Container resource management
- **dockerfile**: JVM containerization patterns

---

## References

- Oracle JVM Documentation
- Java Performance by Scott Oaks (O'Reilly)
- GC Handbook by Charlie Hunt, Binu John
- Optimizing Java (2nd Edition) by Benjamin Evans, James Gough (for deeper study)

