FD 泄露引发的AGP8 build 失败问题

项目升级到 AGP8 以后 一直有个问题,有一个 利用 jacoco 做代码覆盖率的插件 一直会导致项目编译失败,偶现,且 build 失败给出的 堆栈信息迷惑性很强,导致问题排查方向错了,最后发现是 FD 泄露导致的。

调整编译命令 给出更多报错信息以后 如下:

这里就很有迷惑性, 为什么报错在 r8 这里, 甚至堆栈里都明确给出了哪个类的哪个方法出现了问题

这让我的问题排查方向一直陷在 是字节码处理逻辑上的冲突导致, 然后就无用功了很久

最后是通过排除法 逐一把项目中所有字节码处理相关的场景1 个个去掉以后,定位到是某个 task 和 这个 jacoco 的不兼容导致

但是一时半会也没怀疑到跟文件描述符有关。

可以在 build task中 找到最后一个task,加个 doLast 的逻辑 while true 就可以 ,让 build 进程 一直 hang 在那里,方便我们查看进程情况

可以看出来这里 打开了 3600 多个文件实属不太正常

里面还有大量的 class 文件

最后修复了这个文件描述符泄露的问题以后,build 就成功了

理性猜测是agp8 以后,新增的 asm api 本质上是可以并行执行 aop task 的,这里面可能有更加严格的校验机制,导致 FD 泄露以后 校验机制出现异常 最后 build 失败,并且给出了错误的提示信息

脚本

用来统计 jvm 进程 所有文件描述符打开情况(指挥llm 写脚本是真的方便)

shell 复制代码
#!/bin/bash

# 检查 'jps' 命令是否存在
if ! command -v jps &> /dev/null; then
    echo "错误: 未找到 'jps' 命令。请确保 JDK 已安装并且其 bin 目录已添加到您的 PATH 环境变量中。"
    exit 1
fi

# 检查 'lsof' 命令是否存在
if ! command -v lsof &> /dev/null; then
    echo "错误: 未找到 'lsof' 命令。在 macOS 上,它通常是预装的。"
    exit 1
fi

# 显示当前系统时间
echo "扫描时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "正在列出每个 JVM 进程打开的文件描述符详情..."
echo ""

# 使用 jps -l 获取 PID 和主类名
jps -l | while read -r pid name; do
    # 如果进程在 jps 和 lsof 命令之间退出了,lsof 会报错,所以先检查进程是否存在
    if ! ps -p "$pid" > /dev/null; then
        continue
    fi

    # 如果 name 为空 (例如 jps 进程本身),给一个默认值
    if [ -z "$name" ]; then
        name="<jps_process>"
    fi

    # 先用 lsof 统计文件描述符总数
    count=$(lsof -p "$pid" 2>/dev/null | wc -l)

    # 如果进程没有打开任何文件(或已退出),则跳过
    if [ "$count" -eq 0 ]; then
        continue
    fi

    echo "=========================================================================================="
    printf "PID: %-10s | Total FDs: %-8s | Main Class/JAR: %s\n" "$pid" "$count" "$name"
    echo "------------------------------------------------------------------------------------------"
    printf "%-15s %-8s %-12s %-10s %s\n" "COMMAND" "PID" "TYPE" "SIZE/OFF" "NAME"
    echo "------------------------------------------------------------------------------------------"

    # 使用 lsof 列出该进程打开的所有文件,并使用 awk 过滤掉不需要的列
    # 只保留 COMMAND, PID, TYPE, SIZE/OFF, NAME 这几列
    lsof -P -n -p "$pid" 2>/dev/null | awk 'NR>1 {printf "%-15s %-8s %-12s %-10s %s\n", $1, $2, $5, $7, $9}'

    echo "=========================================================================================="
    echo ""
done

echo "统计完成。"
相关推荐
tracyZhang22 分钟前
Android低版本bitmap native分配实现原理
android·性能优化
奥尔特星云大使11 小时前
MySQL 慢查询日志slow query log
android·数据库·mysql·adb·慢日志·slow query log
2501_9159184115 小时前
iOS 框架全解析,原生框架与跨平台框架对比、开发应用打包与 App Store 上架实战经验
android·ios·小程序·https·uni-app·iphone·webview
K24B;15 小时前
多模态大语言模型LISA++
android·人工智能·语言模型·分割·多模态大语言模型
molihuan21 小时前
开源 全平台 哔哩哔哩缓存视频合并 Github地址:https://github.com/molihuan/hlbmerge_flutter
android·flutter·缓存·ffmpeg·开源·github·音视频
奶糖 肥晨21 小时前
批量重命名技巧:使用PowerShell一键整理图片文件命名规范
android·服务器·数据库
Momentary_SixthSense1 天前
如何对较长的Stream链进行Debug
android·java·开发语言
little_fat_sheep1 天前
【Rive】rive-android源码分析
android
教程分享大师1 天前
新魔百和m401h全部版本当贝桌面固件卡刷包和线刷包带adb权限
android
rufeii1 天前
网鼎杯 2020 青龙组
android