1) Approaching Memory Leaks
Memory leaks in Java often manifest as OutOfMemoryError exceptions or rising heap usage visible in monitoring dashboards. My approach:
- Reproduce in staging: Apply the same traffic profile (e.g., JMeter load test).
- Collect a heap dump:
jmap -dump:format=b,file=heap.hprof <PID> - Analyze with tools: Eclipse MAT, VisualVM, or YourKit to detect uncollected references.
- Fix common causes:
- Unclosed streams or ResultSets.
- Static collections holding references.
- Caches without eviction policies (e.g., replace
HashMapwithCaffeine).
2) Profiling and Fixing High CPU Usage
High CPU can stem from tight loops, inefficient queries, or excessive logging.
- Step 1: Sample threads
jstack <PID> > thread-dump.txtIdentify “hot” threads consuming CPU.
- Step 2: Profile with async profilers like async-profiler or Java Flight Recorder.
java -XX:StartFlightRecording=duration=60s,filename=recording.jfr -jar app.jar - Step 3: Refactor:
- Replace
String concatenationin loops withStringBuilder. - Optimize regex (use
Patternreuse instead ofString.matches()). - Review logging level (DEBUG inside loops is expensive).
- Replace
3) Tuning GC for Low-Latency Services
Garbage collection (GC) can cause pauses. For trading, gaming, or API services, tuning matters:
- Choose the right collector:
G1GCfor balanced throughput and latency (default in recent JDKs).ZGCorShenandoahfor ultra-low latency workloads (<10ms pauses).
- Sample configs:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled - Monitor GC logs with GC Toolkit or Grafana dashboards.
4) Handling Database Bottlenecks
Spring apps often hit bottlenecks in DB queries rather than CPU.
- Enable SQL logging: in
application.propertiesspring.jpa.show-sql=true - Profile queries: Use
p6spyor database AWR reports. - Fixes:
- Add missing indexes (
EXPLAIN ANALYZEis your friend). - Batch inserts (
saveAll()in Spring Data withhibernate.jdbc.batch_size). - Introduce caching (Spring Cache, Redis) for hot reads.
- Use connection pools like HikariCP with tuned settings:
spring.datasource.hikari.maximum-pool-size=30
- Add missing indexes (