为何我的Kotlin Gradle构建因退出码137异常终止?
遇到这种Gradle测试执行完却以退出码137终止的情况,核心原因几乎都是系统内存耗尽,强制杀死了Gradle或测试进程——哪怕你看到测试都“通过”了,也可能是测试刚执行完,Gradle后续的清理或报告生成阶段内存不够被干掉了。结合你用的Kotlin 1.2.40、Gradle 4.3、Java 8环境,给你几个针对性的解决方向:
1. 单独配置测试任务的JVM内存参数
Gradle自身的JVM内存和测试任务运行的JVM是相互独立的——你给Gradle加内存,不代表测试进程能用到足够的内存。Kotlin项目因为字节码结构的原因,元空间(Metaspace)占用往往比Java项目高,很容易触发内存不足。在你的build.gradle中添加以下配置:
test { // 根据CI环境可用内存调整堆内存,比如1g、1.5g maxHeapSize = "2g" // 限制元空间大小,避免类加载过多导致内存溢出 jvmArgs "-XX:MaxMetaspaceSize=512m" }
2. 检查CI环境的总内存配额
很多CI平台默认的内存配额并不高(比如2GB左右)。如果Gradle自身的内存占用+测试进程的内存占用+系统其他进程的开销超过了这个配额,系统就会强制终止进程。你可以在CI脚本开头添加内存检查命令,确认可用资源:
# Linux环境下查看内存详情 free -h
根据输出调整各个部分的内存参数,确保总占用不超过CI环境的可用内存。
3. 升级Gradle和Kotlin版本(优先兼容旧项目的小版本升级)
你当前使用的Gradle 4.3和Kotlin 1.2.40都是比较老旧的版本,这些版本存在不少内存管理的bug和性能问题。比如Gradle 4.10.x是和Kotlin 1.2.40兼容的最高Gradle版本,相比4.3有不少内存优化;如果项目允许,升级到Kotlin 1.3.x + Gradle 6.x的组合,内存使用效率会提升很多。
4. 禁用测试并行(避免多进程内存叠加)
虽然Gradle 4.3还没有正式支持测试并行,但有些第三方插件可能会默认开启并行执行测试。强制设置单线程执行测试,减少内存开销:
test { maxParallelForks = 1 }
5. 排查测试进程的内存泄漏
如果以上方法都无效,可能是某个测试用例存在内存泄漏问题。你可以给测试任务添加堆转储参数,当发生OOM时生成堆快照,方便后续分析:
test { jvmArgs "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/tmp/test-heapdump.hprof" }
在CI环境中配置保存这个堆快照文件(比如上传到CI的artifact仓库),下载后用MAT(Memory Analyzer Tool)等工具分析,定位内存泄漏的根源。
内容的提问来源于stack exchange,提问作者Steven Grimm

