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 "统计完成。"
相关推荐
SharpCJ9 小时前
Android 开发者为什么必须掌握 AI 能力?端侧视角下的技术变革
android·ai·aigc
_李小白9 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习
JJay.10 小时前
Kotlin 高阶函数学习指南
android·开发语言·kotlin
jinanwuhuaguo10 小时前
截止到4月8日,OpenClaw 2026年4月更新深度解读剖析:从“能力回归”到“信任内建”的范式跃迁
android·开发语言·人工智能·深度学习·kotlin
JJay.10 小时前
Android Kotlin 协程使用指南
android·开发语言·kotlin
BLUcoding11 小时前
Android 布局介绍
android
summerkissyou198711 小时前
android-蓝牙-状态和协议值总结及监听例子
android·蓝牙
徒 花11 小时前
数据库知识复习05
android·数据库
提子拌饭13313 小时前
番茄时间管理:鸿蒙Flutter 实现的高效时间管理工具
android·flutter·华为·架构·开源·harmonyos·鸿蒙
4311媒体网13 小时前
帝国CMS二次开发实战:精准实现“最新资讯”标识与高亮判断
android