Java Performance Optimization: Eight Anti-Patterns That Slow Down Your Code

✍️ OpenClawRadar📅 Published: March 20, 2026🔗 Source
Java Performance Optimization: Eight Anti-Patterns That Slow Down Your Code
Ad

Performance Improvements from Fixing Anti-Patterns

Jonathan Vogel built a Java order-processing app that initially had 1,198ms elapsed time, handled 85,000 orders per second, used just over 1GB heap, and had 19 GC pauses. After fixing eight anti-patterns without architectural changes or JDK updates, performance improved to 239ms elapsed time, 419,000 orders per second, 139MB heap, and 4 GC pauses. This represents 5x throughput, 87% less heap usage, and 79% fewer GC pauses.

Eight Java Performance Anti-Patterns to Fix

  • String concatenation in loops - O(n²) copying from immutability
  • O(n²) stream iteration inside loops - streaming the full list per element
  • String.format() in hot paths - slowest string builder, parses format every call
  • Autoboxing in hot paths - millions of throwaway wrapper objects
  • Exceptions for control flow - fillInStackTrace() walks the entire call stack
  • Too-broad synchronization - one lock becomes the bottleneck
  • Recreating reusable objects - ObjectMapper, DateTimeFormatter, Gson per call
  • Virtual thread pinning (JDK 21-23) - synchronized + blocking I/O pins carriers
Ad

Detailed Examples and Fixes

1. String Concatenation in Loops

Problem code:

String report = "";
for (String line : logLines) {
    report = report + line + "\n";
}

This creates O(n²) copying due to String immutability. BellSoft JMH benchmarks show that when n grows by 4x, loop-concatenation slows down by more than 7x.

Fix:

StringBuilder sb = new StringBuilder();
for (String line : logLines) {
    sb.append(line).append("\n");
}
String report = sb.toString();

Note: Since JDK 9, the compiler optimizes single-line concatenation like "Order: " + id + " total: " + amount, but this optimization doesn't carry into loops.

2. Accidental O(n²) with Streams Inside Loops

Problem code:

for (Order order : orders) {
    int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
    long countForHour = orders.stream()
        .filter(o -> o.timestamp().atZone(ZoneId.systemDefault()).getHour() == hour)
        .count();
    ordersByHour.put(hour, countForHour);
}

This pattern accounted for nearly 71% of CPU stack samples in the JFR recording. With 10,000 orders, it performs 100 million comparisons instead of a single pass.

Fix:

for (Order order : orders) {
    int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
    ordersByHour.merge(hour, 1L, Long::sum);
}

This provides O(n) performance with one pass. You could also use Collectors.groupingBy(... Collectors.counting()) in a single stream pipeline.

The article is part 1 of a 3-part Java Performance Optimization series, with parts 2 and 3 coming soon. Part 2 will walk through the profiling data behind these numbers, including flame graphs and which methods were actually hot.

📖 Read the full source: HN AI Agents

Ad

👀 See Also

Setting up OpenClaw on macOS with a unified AI provider endpoint
Guides

Setting up OpenClaw on macOS with a unified AI provider endpoint

A developer shares their experience installing OpenClaw on macOS, including the requirement for Node.js 24, using Homebrew for installation, configuring a custom OpenAI-compatible provider like ZenMux, and setting up a background daemon. Key troubleshooting tips include WhatsApp's default message blocking and using the openclaw doctor command.

OpenClawRadar
OpenClaw setup checklist: six critical steps for new users
Guides

OpenClaw setup checklist: six critical steps for new users

A Reddit post outlines six essential configuration steps for OpenClaw users: change default model from Opus to Sonnet to reduce costs, lock gateway host to 127.0.0.1 for security, create SOUL.md for agent personality, avoid installing skills initially, don't create multiple agents, and use /new command to manage conversation context.

OpenClawRadar
Understanding AI Agent Architecture: Deterministic vs Probabilistic Layers
Guides

Understanding AI Agent Architecture: Deterministic vs Probabilistic Layers

A Reddit user shares a mental model for AI agent systems that separates deterministic layers (scripts, commands, APIs) from probabilistic layers (LLM reasoning and decisions). The key insight: push as much work as possible to the deterministic side.

OpenClawRadar
Claude vs GPT for PhD Academic Writing: Preserving Technical Meaning in Methods Sections
Guides

Claude vs GPT for PhD Academic Writing: Preserving Technical Meaning in Methods Sections

A PhD candidate compares Claude and GPT for polishing computer vision / hardware co-design papers, finding Claude more reliable at preserving technical meaning and argument structure while GPT sometimes oversimplifies claims.

OpenClawRadar