You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMH基准测试ArrayList.add方法时出现OutOfMemoryError问题

问题根源

  1. 你错误使用了@Setup(Level.Trial)注解:该级别代表整个测试周期(包含所有预热、测量迭代)仅执行一次列表初始化,后续所有@Benchmark方法的调用都是往同一个全局列表追加元素,全程不会清空列表。
  2. 你的测试采用吞吐量模式,单轮预热迭代就要连续跑5秒,从错误日志能看到每秒插入量级达2200万次,仅几秒钟列表长度就会突破千万级,ArrayList扩容时需要申请连续大数组,很快就会耗尽4G堆内存触发OOM。
  3. 你定义的iterations参数完全没有在测试逻辑中用到,实际运行是无限制插入,和你预期的固定次数插入测试逻辑完全不符。

修复方案

方案1:调整Setup级别,避免内存无限累积

将Setup的生效级别改为每次迭代前重新初始化列表,避免单轮迭代内列表无限扩容:

// 仅修改@Setup的级别参数即可
@Setup(Level.Iteration)
public void setup() {
    arrayList = new ArrayList<>();
    linkedList = new LinkedList<>();
}

如果单轮迭代时间还是设置为5秒,依然可能出现OOM,建议同步缩短单轮迭代时长,或者改用第二种方案。

方案2:按指定插入次数测试,符合你预设的参数逻辑

修改基准方法,每次调用都新建列表,插入指定数量元素后丢弃,完全避免内存泄漏,同时利用你定义的iterations参数:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 5, time = 5)
@Measurement(iterations = 10, time = 5)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class ListAddBenchmark {

    private int NUMBER = 123;

    @Param({"1000","100000","1000000"})
    public int iterations;

    // 注入JMH提供的Blackhole避免JIT优化掉未使用的列表对象
    @org.openjdk.jmh.infra.Blackhole
    public Blackhole blackhole;

    @Benchmark
    public void arrayListBenchmark() {
        List<Integer> arrayList = new ArrayList<>();
        for (int i = 0; i < iterations; i++) {
            arrayList.add(NUMBER);
        }
        blackhole.consume(arrayList);
    }

    @Benchmark
    public void linkedListBenchmark() {
        List<Integer> linkedList = new LinkedList<>();
        for (int i = 0; i < iterations; i++) {
            linkedList.add(NUMBER);
        }
        blackhole.consume(linkedList);
    }
}

额外注意

如果要测试列表已有指定数量元素时的尾插性能,可以在@Setup(Level.Iteration)方法中先给列表填充对应数量的初始元素,再执行插入测试,依然要保证每次迭代都会重新初始化列表,避免元素持续累积。

内容的提问来源于stack exchange,提问作者Toby Cook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 13:36:02