Android 编译 gradle 内存 OOM 解决之路(一)

简介: Android 编译 gradle 内存 OOM 解决之路

背景


最近项目在编译,编译多次之后,有挺多人反馈会出现 OOM 的,在项目的根目录下面会出现 hs_err_pid*.log 的错误文件。内容大概如下


ba613cd0cd5dd862aa9119325a3fffda_986d75087c70e2451098d7db560f5ab7.png


这个对我们的开发效率还是有挺大影响的,如果能够解决,对我们的开发效率还是有一定提升的。因此,我们尝试进行解决。


探索原因


从报错的信息来看,‘jar transform Thread’ 有时候的线程数非常多, 很有可能是同时开启的线程数过大,导致内存不足,最终 OOM。


从线程名是 ‘jar transform Thread’ ,根据经验,我们第一时间想到可能是 transform 相关的。


于是,我们找项目当中 transfrom 相关的, 从 buildScan 文件中,找 transfrom 相关的


fb2d08fd2cba75921afca90431a352e3_eb849ef08a0e458fad40bcf2b72ae5e7.png


发现主要有几个


  1. transformClassesWithRealmTransformerForDebug
  2. transformClassesWithCom.xx.xx.gradle.plugin.hilt.HiltContextWrapperRemovePluginForDebug
  3. transformDebugClassesWithAsm


很快我们找到 Hilt, Realm 里面 transform 里面的代码,发现里面的 Thread Name 都不是 jar transform Thread。那应该不是这两个的原因。


讨论之后,我们尝试 dump 编译时 Java 进程的内存信息,看能不能复现?


首先,我们先确定当前进程的 PID


3f54813fc697d6ccd7441b7088d02b80_866ad1c1111cb18d4cea18c4ca5fcbd2.png


接着我们借助 VisualVM 这个工具,dump 下 JVM 编译时候的进程,编译的时候发现,线程数有时候会越来越多。


8d5b928b41bcee5a74363bd3db617588_d9a5944a2d908522030cadd89d3126f3.png


于是,我们在想能不能 debug 创建线程的地方,于是,我们在 java.lang.Thread#setName 这里设置条件断点 name.contains("jar transform")


68430a733572f185653a402deeb9994a_59ccdb48be5daa03c640c2a9c2ddf636.png


debug gradle assembleDebug 任务,很快我们发现,调用栈关系如下


3c3091509e9f7dc3865e1d93114a8779_801af5630465093e10c0136ac0e0f7a9.png


我们重点关注到了几个跟线程相关的东西


198569d65064abc0735a474e26f3434a_dd634c46d7f1b94a1e364af2315c0573.png


我们跟踪进去,发现这个线程池的核心线程数设置为 2147483647


7c57a1829769f9a4fb689da6d33ca847_9ba168670059b22d7fd17b80844d4d33.png


而上面的线程数不断增多,并且线程名包括 “jar transform”, 那很有可能就是这个线程池了。


我们逐一排查,发现线程池 executor 是在这里传递进来的


49d4b957923d21bfc4234162925c704a_eab8bd761453da20b73167e6da720bd3.png


跟踪代码,很快我们发现创建改线程池 executor 的地方DefaultCachedClasspathTransformer#executor


bc9a1cdf42835b481d87105aab92365a_9ab0f1a3db06ac0bc742412bfe6d7e8e.png


他这里果然没有限制线程的数量。


而我们项目中的 gradle 代码是 6.9.1,于是在想,我们去跟官方最新代码对比一下。


相关文章
|
2月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
4月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
332 1
|
2月前
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
112 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
编译器 Android开发
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
|
2月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
2月前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
110 0
玩转安卓之配置gradle-8.2.1
|
4月前
|
Android开发
Android Studio: 解决Gradle sync failed 错误
本文介绍了解决Android Studio中出现的Gradle同步失败错误的步骤,包括从`gradle-wrapper.properties`文件中获取Gradle的下载链接,手动下载Gradle压缩包,并替换默认下载路径中的临时文件,然后重新触发Android Studio的"Try Again"来完成同步。
1730 0
Android Studio: 解决Gradle sync failed 错误
|
4月前
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
193 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
28天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
232 1