性能优化与故障排查:度量、定位、优化闭环(JFR/Profiler/火焰图)
大约 4 分钟
性能优化与故障排查:度量、定位、优化闭环(JFR/Profiler/火焰图)
新手一屏速览
- 先度量后优化:明确 SLO/指标;JFR/Profiler/日志/指标联动观察
- 火焰图找热点:锁争用/分配/IO;优化以假设为起点,以基准验证为终点
- 优化闭环:变更小步、记录上下文、建立回归基准与告警阈值
1. 指标体系与 SLO
- 业务指标(QPS/延迟/错误率)与资源指标(CPU/堆/GC/IO)对齐;定义 SLO 与告警
- 在关键路径埋点,建立可观测性基线(Trace/Metrics/Logs)
2. JFR/Profiler 工具链
- JFR(低开销事件)采集方法采样、锁事件、分配、GC;结合 GUI 诊断
- 分析器(Async Profiler/JMC)生成火焰图,识别热点与阻塞
3. 热点类型与定位策略
- CPU 热点:算法/数据结构选择、装箱与分配、内联与去虚拟化
- 锁争用:缩小临界区、读写分离、无锁结构;监控阻塞与 Owner
- IO/网络:批量与缓冲、异步、连接复用;确认下游瓶颈
4. JIT 与内联
- 小函数与无捕获 Lambda 更易内联;分派去虚拟化(final/静态绑定)
- 热分支外提、避免异常路径污染、减少多态层级
5. 配置与代码协同
最近建一些几十个工作内推群,各大城市都有,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。 欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。

- GC 参数与堆设置服务于业务画像;线程池与队列长度按压测与回放调优
- 调优不要只调参数;必要时修改代码与架构以消除根本瓶颈
6. 压测与回归
- 固定环境与参数;基准数据具备代表性;关注 P50/P95/P99 全分位
- 建立自动化回归基准与阈值化告警,防止“优化回退”
7. 练习
- 使用 JFR 捕获一次完整压测,输出火焰图并定位前三热点
- 对热点函数进行去虚拟化与数据结构替换,提交前后基准对比报告
示例代码(可直接复制运行)
示例一:极简基准对比(数组 vs ArrayList)
import java.util.*;
public class MiniBenchArrayVsList {
static long sumArray(int[] a){
long s=0; for (int v : a) s+=v; return s;
}
static long sumList(List<Integer> l){
long s=0; for (int i=0;i<l.size();i++) s+=l.get(i); return s; // 装箱访问慢
}
static long time(Runnable r){
long t0=System.nanoTime(); r.run(); return System.nanoTime()-t0;
}
public static void main(String[] args){
int n=5_000_000;
int[] arr=new int[n]; Arrays.setAll(arr, i->i);
List<Integer> list=new ArrayList<>(n); for(int i=0;i<n;i++) list.add(i);
long t1=time(()-> System.out.println(sumArray(arr)));
long t2=time(()-> System.out.println(sumList(list)));
System.out.println("array(ms)="+t1/1_000_000.0+" list(ms)="+t2/1_000_000.0);
}
}示例二:锁争用与临界区缩小
public class LockContention {
static final Object lock = new Object();
static long shared = 0;
static void bad() {
synchronized (lock) {
for (int i=0;i<1_000_000;i++) shared++; // 临界区过大
}
}
static void good() {
long local = 0;
for (int i=0;i<1_000_000;i++) local++; // 无锁累加
synchronized (lock) { shared += local; } // 缩小临界区
}
static long bench(Runnable r) {
long t0 = System.nanoTime(); r.run(); return System.nanoTime()-t0;
}
public static void main(String[] args) {
System.out.println("bad(ms)="+bench(LockContention::bad)/1_000_000.0);
System.out.println("good(ms)="+bench(LockContention::good)/1_000_000.0);
}
}示例三:去虚拟化(final 类)与内联
public class Devirtualization {
interface Op { int apply(int x); }
static class Add1 implements Op { public int apply(int x){ return x+1; } }
static final class FinalAdd1 implements Op { public int apply(int x){ return x+1; } }
static long loop(Op op){
long s=0; for (int i=0;i<50_000_000;i++) s+=op.apply(i); return s;
}
public static void main(String[] args){
System.out.println(loop(new Add1()));
System.out.println(loop(new FinalAdd1()));
// JIT 更易对 FinalAdd1 去虚拟化并内联
}
}示例四:简单分配热点对比
import java.util.*;
public class AllocationHotspot {
static long boxedSum(int n){
Long s = 0L;
for (int i=0;i<n;i++) s += i; // 频繁装箱
return s;
}
static long primitiveSum(int n){
long s = 0L;
for (int i=0;i<n;i++) s += i; // 原始类型
return s;
}
public static void main(String[] args){
int n = 50_000_000;
long t1 = System.nanoTime(); System.out.println(boxedSum(n)); long d1 = System.nanoTime()-t1;
long t2 = System.nanoTime(); System.out.println(primitiveSum(n)); long d2 = System.nanoTime()-t2;
System.out.println("boxed(ms)="+d1/1_000_000.0+" primitive(ms)="+d2/1_000_000.0);
}
}