A Java 21 order analytics pipeline built to demonstrate common performance anti-patterns and how to find them with JDK Flight Recorder (JFR) and JDK Mission Control (JMC).
This app was originally built for a DevNexus 2026 talk (March 10, 2026) and is the demo application referenced in the blog series:
- Part 1: Java Is Fast. Your Code Might Not Be.
- Part 2: One Method Was Using 71% of CPU. Here's the Flame Graph.
The main branch contains the unoptimized code with intentional performance anti-patterns on the hot path:
- O(n²) stream-inside-loop in
TrendDetector.detect() - String concatenation with
+in a loop inRevenueAnalyzer.analyze() Pattern.compile()on every call inOrderValidator.validate()String.format()in a hot path inOrderGenerator.generateOrder()- Autoboxing with
List<Double>/List<Integer>inFraudScorer.score() synchronizedmethod with string concatenation inAnalyticsAccumulator.accumulate()LinkedListwith indexed access andHashtableinReportGenerator.generate()
The performance-optimized branch contains the fixes. Run git diff main..performance-optimized to see exactly what changed.
- JDK 21 (e.g., Amazon Corretto 21)
- Maven 3.8+
java -version # should show 21.x
mvn -version # should show 3.8+mvn clean package
java -cp target/classes com.demo.orderanalytics.AppThis processes 100,000 orders across 100 batches using virtual threads and prints throughput metrics and an analytics report.
java -cp target/classes com.demo.orderanalytics.App \
--orders 200000 \
--batch-size 2000| Flag | Default | Description |
|---|---|---|
--orders <n> |
100000 | Total orders to process |
--batch-size <n> |
1000 | Orders per batch |
--profile |
off | Enable JFR recording via the app's built-in controller |
--output <path> |
recording.jfr | JFR output file path |
Use the JDK's built-in profile settings for comprehensive event capture (CPU sampling, allocation tracking, GC events, thread contention):
java -XX:StartFlightRecording=filename=recording.jfr,settings=profile \
-cp target/classes com.demo.orderanalytics.App- Download JDK Mission Control
- File → Open File → select
recording.jfr - Start with the Java Application overview tab (CPU, heap, GC)
- Go to Method Profiling for the flame graph
- Go to Lock Instances (under Threads) for contention data
A pre-captured recording.jfr is included in this repo from the unoptimized baseline. You can open it in JMC immediately to see the anti-patterns in action.
The default config (100 virtual threads) may not generate enough lock contention to cross JFR's reporting threshold. To see contention on AnalyticsAccumulator, run with higher concurrency:
java -XX:StartFlightRecording=filename=contention.jfr,settings=profile \
-cp target/classes com.demo.orderanalytics.App \
--orders 500000 --batch-size 200Then open contention.jfr in JMC and navigate to Threads → Lock Instances.