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

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

对比官方 gradle 代码


我们首先 clone 官方代码 gradle,找到 DefaultCachedClasspathTransformer,

发现最新代码已经进行了修改,限制了线程的数量。改为跟 CPU 核心数挂钩。


3f54adebc21a5bae83ce5e9990e431f2_28697a03d66c1e3b3c664b4597557fdf.png


而他是在什么时候进行了修改了,其实很简单,我们可以借助 git 命令,找到他属于哪一个 TAG.


git tag --contains 2a1e74166bc82607e15de78002ef56582b34af0d


ef964aae64de99621944e20df271d82d_c32cf538489b08f26412029c7e8dc80b.png


很快我们发现了,他在 gradle 7.0 上面对线程池的线程数进行了限制,改为跟 CPU 核心数挂钩。


思考


先来思考一个问题,可能很多人有同样的疑问。


为什么有的机器没出现有的机器会出现,⽐如我同事的mac就没有发现

我么先来看一下 java tranfrom 线程是干什么用的,


我们可以看这里的代码

org.gradle.internal.classpath.DefaultCachedClasspathTransformer.TransformFile#schedule


8c0ea1e3df6cb15c992acc655c553ed0_2317890d1581e523e58f63c18bfe88ff.png


跟踪下去,你会发现主要是一些 IO 读取操作。


如果说你的机器磁盘性能比较好,那么 IO 读取比较快,线程干完工作之后,就会自动销毁,出现这样现象的可能性会比较低。如果磁盘性能较差,出现的可能性会比较大。


问题解决


既然怀疑问题是因为这里的线程数引起的,于是第一时间我们想到了几种方法


  1. 反射修改线程池的数量
  2. 升级 gradle 版本


于是,我们跟中代码,试试反射能不能修改代码,但很快,我们发现,并没有找到一个好的 hook 点,无法修改。


可能有人会想到 epic,没错,刚开始我也想用 epic。但是 epic 是基于安卓 ART 虚拟机的,而我们编译的时候,是基于 JVM 的,epic 是无法使用的。


接着我们尝试了第二种方法,尝试升级 gradle 版本到 7.0,折腾了一fang之后,发现升级要适配的东西还是蛮多的,一下子无法解决


  1. maven repo 仓库设置 allowInsecureProtocol
  2. grrovy 版本冲突
  3. JavaParser 错误


总之,错误是解决完一个接着一个,还是挺多坑的


柳暗花明又一村


跟汉光爷讨论之后,汉光爷说能不能自己编译一个版本出来。他在官网上找到了编译 gradle 版本的方法


2489a00d8ef6bf4bcd8b43164dd2b4a7_edf0bcfe06250af185979acb9f64bb65.png


编译完成之后,上传到 CC 的 S3 服务器上面,我们在 gradle-wrapper.properties 下面修改,替换成自己的 gradle 版本


#Thu May 30 18:31:45 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
# 解决编译线程数过多,导致 OOM 的问题
distributionUrl=https://xx.cn/static/gradle/gradle-6.9.3-all.zip


再次编译,可以看到 jar transform 相关的线程数,最多变为 8 了,因为我的电脑是 8 核单核心的。


4861434a8fcd328279615209d6d381fe_9e5c21f1127efd5d2894e55de85261d0.png


到此,我们对 gradle jar transfrom thread 的线程数进行了限制,合理应该是不会再出现 OOM 了,如果还会出现,可以保留现场,找我或者汉光看看。


总结


可以看到,我们这次的问题解决思路大概是这样的。


  1. 从 error 日志排查发现,很有可能跟 transfrom 相关
  2. 排查项目里面 transfrom 相关的,有没有 jar transform Thread 相关的
  3. dump JVM 内存,看线程相关的,观察 jar transform Thread 是否异常
  4. debug gradle assemble 任务,观察 线程名包括 jar transform Thread Thread 的调用堆栈
  5. 分析 调用堆栈,找到原因
  6. 结合 gradle 官方代码,查看问题是否已经解决


那有没有更快的方法呢?


其实如果一开始能确定是 gradle 问题的话,可以直接在 gradle 里面搜索字符串 jar transforms,然后再一步步反推,其实也是可以的。


相关文章
|
14天前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
111 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
4月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
6月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
447 1
|
4月前
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
4月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
269 22
|
5月前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
4月前
|
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开发知识可参考相关书籍。
142 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
4月前
|
编译器 Android开发
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
|
4月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
4月前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
199 0
玩转安卓之配置gradle-8.2.1

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 3
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 4
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 5
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 6
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 7
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 8
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 9
    MySQL底层概述—1.InnoDB内存结构
  • 10
    Pandas高级数据处理:内存优化