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

Gradlew运行大量测试时OutOfMemoryError的配置优化求助

解决测试阶段OutOfMemoryError及GCLocker警告的配置优化

我维护的应用包含500-700个测试用例,执行./gradlew clean build时部分测试会启动Spring上下文,多次调整build.gradle的测试配置后,仍频繁出现OutOfMemoryError,日志中有GCLocker相关警告,且多线程抛出内存不足异常。当前test配置如下:

test {
    useJUnitPlatform()
    maxParallelForks = 1          
    forkEvery = 10              

    jvmArgs = [
            '-Xmx2g',
            '-XX:MaxMetaspaceSize=512m',
            '-XX:+UseG1GC',
            '-XX:G1HeapRegionSize=8m',
            '-XX:InitiatingHeapOccupancyPercent=20',
            '-XX:ConcGCThreads=1',
            '-XX:ParallelGCThreads=1',
            '-XX:MaxGCPauseMillis=300',
            '-XX:+HeapDumpOnOutOfMemoryError', 
            '-XX:HeapDumpPath=build/heapdumps',
            '-Xlog:gc*:build/gc.log'   
    ]
    systemProperties = [
            "feign.client.config.default.connectTimeout"   : "5000",
            "feign.client.config.default.readTimeout"      : "5000",
            "feign.httpclient.maxConnections"              : "3",
            "hikari.maximumPoolSize"                       : "2"
    ]
}

核心优化方案

1. 调整GC配置,缓解GCLocker阻塞

GCLocker警告多与JNI代码阻塞GC有关,当前GC线程数过低会直接拖慢回收效率:

  • 移除-XX:ConcGCThreads=1和-XX:ParallelGCThreads=1,让JVM根据CPU核心自动分配线程数;若需手动设置,建议设为CPU核心数的1/2(比如4核机器设为2)
  • 暂时切换到并行GC组合:-XX:+UseParallelGC + -XX:+UseParallelOldGC,并行GC在批量测试场景下的内存回收效率更稳定,能减少GCLocker触发概率

2. 强化测试进程隔离,避免内存积累

当前配置的进程隔离策略不足以应对上下文启动类测试的内存开销:

  • 提升maxParallelForks到CPU核心数的1/2(需确保机器内存充足,比如2个进程配Xmx2g,需预留至少4g+系统内存)
  • 降低forkEvery值至5,更频繁重启JVM进程,减少单个进程内的内存泄漏积累
  • 可选添加forkMode = "perTest",强制每个测试类启动独立进程,彻底隔离上下文内存(若测试执行时间可接受)

3. 精细化内存参数调整

  • 添加-Xms2g,让JVM初始堆等于最大堆,避免堆扩容带来的额外GC压力
  • 将-XX:InitiatingHeapOccupancyPercent调回默认值45,当前20的阈值会导致GC过于频繁,反而加剧CPU和内存开销
  • 移除-XX:MaxGCPauseMillis=300,测试场景下无需严格的暂停时间限制,强制目标会导致G1优先回收小区域,加剧内存碎片化

4. 测试代码辅助优化

  • 对启动Spring上下文的测试类,添加@DirtiesContext注解,标记测试后销毁上下文,避免上下文复用导致的内存泄漏
  • 在测试类的@AfterAll方法中手动关闭Feign连接池和Hikari数据源,确保资源及时释放

优化后的示例配置

test {
    useJUnitPlatform()
    maxParallelForks = 2          
    forkEvery = 5              
    forkMode = "perTest" // 可选,按测试类隔离进程

    jvmArgs = [
            '-Xms2g',
            '-Xmx2g',
            '-XX:MaxMetaspaceSize=512m',
            '-XX:+UseParallelGC',
            '-XX:+UseParallelOldGC',
            '-XX:+HeapDumpOnOutOfMemoryError', 
            '-XX:HeapDumpPath=build/heapdumps',
            '-Xlog:gc*,gc+heap=debug:file=build/gc.log:time,uptime:filecount=5,filesize=10m'   
    ]
    systemProperties = [
            "feign.client.config.default.connectTimeout"   : "5000",
            "feign.client.config.default.readTimeout"      : "5000",
            "feign.httpclient.maxConnections"              : "3",
            "hikari.maximumPoolSize"                       : "2"
    ]
}

内容的提问来源于stack exchange,提问作者Назар

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 12:08:09