Fixrleak: 使用 GenAI 修复 Java 资源泄露
引言
资源泄露,即文件、数据库连接或流等资源在使用后未被正确释放,是 Java 应用程序中一个长期存在的问题。 这些泄露可能导致性能下降和系统故障。 虽然像 SonarSource SonarQube™ 这样的工具可以有效地识别此类泄露,但修复过程仍然是手动的、耗时的并且容易出错。 为了解决这个问题,我们开发了 FixrLeak,这是一个基于生成式 AI 的框架,可以自动检测和修复资源泄露。 FixrLeak 结合了抽象语法树 (AST) 分析和生成式 AI (GenAI),以生成准确、符合习惯用法的修复,同时遵循 Java 最佳实践,例如 try-with-resources。 FixrLeak 部署在 Uber 广泛的 Java 代码库中,可以显着减少手动工作量,提高开发人员的生产力,并提高代码质量,从而展示了 AI 驱动的解决方案在大型软件工程中的变革潜力。
背景
理解 Java 中的资源泄露
当程序在使用后未能正确释放文件、数据库连接或流等资源时,就会发生资源泄露。 这些泄露可能导致严重的问题,包括性能下降、应用程序故障以及由于资源耗尽而无法处理其他操作。 例如,如果文件描述符未被快速释放,它可能会阻止应用程序打开新文件,最终导致系统不稳定。
考虑以下示例,其中使用 BufferedReader
对象从文件中读取数据。 在原始代码(图 1)中,读取器未正确关闭,从而导致资源泄露。 从历史上看,开发人员依赖 try/catch/finally 块来处理此类情况,但是缺少或不正确的 finally 块通常会导致泄露。 现代 Java 最佳实践建议使用 try-with-resources 语句,该语句可以显着减少样板代码,并确保资源安全释放,即使在执行过程中发生异常也是如此。
图 1:原始代码,存在资源泄露。
图 2:使用 try-with-resources 修复后的代码。
在修改后的版本(图 2)中,BufferedReader
是在使用 try-with-resources 语句的 try 块中声明的,从而确保在不再需要时自动关闭它。 这种做法简化了代码,并消除了资源泄露的风险,使其成为现代 Java 编程的一项重要技术。
解决资源泄露:FixrLeak 之前的工作
在 FixrLeak 之前,资源泄漏修复要么是手动的,要么由早期的自动化工具处理。 RLFixer 是一种非 GenAI 工具,它依赖于预先设计的模板和分析框架,如 WALA。 虽然这些工具对于某些泄漏有效,但在像 Uber 这样的大规模代码库中,它们难以扩展,并且需要为每个新的编程习惯用法进行广泛的手动设置。
像 InferFix 这样基于 GenAI 的解决方案,通过使用大型语言模型来自动化修复,从而有所改进。 然而,InferFix 有其局限性,包括只有 70% 的修复准确率,以及在需要高级代码分析的复杂泄漏方面面临的挑战。 此外,它依赖于专有模型,这些模型无法轻松适应不断发展的技术。
FixrLeak 从这些经验中吸取教训,采用可扩展的、无模板的生成式 AI 方法,可以在 Uber 的代码库中无缝运行。 它专注于易于修复的泄漏,以实现更高的准确性,使其成为工业规模资源泄漏管理的游戏规则改变者。
架构
图 3:使用 Fixrleak 的资源泄漏修复工作流程。
FixrLeak 的总体流程如图 3 所示。我们目前专注于修复资源生命周期不超过分配该资源的函数范围的泄漏。
输入收集
FixrLeak 首先扫描 SonarQube 报告的资源泄漏,收集关键细节,如文件名和行号。 为了解决代码库中的更改,它使用基于文件和函数名称的确定性哈希,确保准确跟踪泄漏及其修复。 一旦识别出来,FixrLeak 就会使用 Tree-sitter 库来解析代码并提取相关的函数进行分析。
AST 级别分析
修复资源泄漏并不总是那么简单——盲目地应用修复可能会导致新的问题,比如 use-after-close 错误。 例如,如果像 BufferedReader
这样的资源是从方法返回的,那么过早地关闭它可能会破坏其调用者处的代码。 为了避免此类陷阱,FixrLeak 使用 Tree-sitter 来执行 AST(抽象语法树)分析。
此分析确保 FixrLeak 跳过资源作为参数传递、返回或存储在字段中的函数,因为这些资源的生命周期通常超过函数的范围。 通过仅关注可以安全修复的场景,FixrLeak 可以提供精确、可靠的修复,同时将更复杂的情况留给调用者级别的高级分析。
图 4:无法在函数中使用 try-with-resources 修复的示例。
Prompt 工程
一旦资源泄漏通过了初始检查,FixrLeak 就会创建一个定制的 prompt 并将其发送到生成式 AI 模型,例如 OpenAI® ChatGPT-4O。 AI 会回复一个建议的修复,FixrLeak 通过将原始的、有泄漏的函数替换为新的、无泄漏的版本来应用该修复。 最后,FixrLeak 生成一个 pull request,从而简化了开发人员审查和批准修复的过程。
Pull Request 验证
在提交 pull request 之前,FixrLeak 会运行多个验证检查,以确保修复是可靠的。 它验证目标二进制文件是否成功构建,运行所有现有测试以确认没有任何东西被破坏,并且还可以使用 SonarQube 重新检查代码,以确认资源泄漏已得到解决。 这种彻底的测试确保了高质量的修复,开发人员可以放心地审查和合并。
代码审查
最后一步是开发人员进行代码审查,以接受 pull request。 通常,他们只需要一键接受即可。
在 Uber 的用例
为了测试 FixrLeak,我们将其应用于 Uber 的 Java 代码库中 SonarQube 识别出的 124 个资源泄漏。 在排除了已弃用代码中的 12 个案例后,FixrLeak 的 AST 级别分析处理了剩余的 112 个泄漏,从而确保仅在资源被限制在函数范围内时才应用修复。 这种对函数内泄漏的关注发挥了生成式 AI 的优势,从而实现了很高的成功率。
在 102 个符合条件的案例中,FixrLeak 成功地自动修复了 93 个泄漏。
通过关注范围明确的问题并使用高级分析,FixrLeak 已被证明是一种非常有效的工具,可以提高代码质量并减少人工干预。 这种方法加速了开发,并确保 Uber 的系统在大规模下保持稳健和高效。 Fixrleak 继续定期在 Java 代码库上运行,并将快速生成未来引入的资源泄漏的修复。
后续步骤
展望未来,我们的目标是在以下几个关键领域扩展 FixrLeak 的功能:
- 支持过程间修复:增强该工具以处理跨越多个函数或方法的资源泄漏。
- 基于 GenAI 的泄漏检测:结合生成式 AI 来识别资源泄漏,补充现有的检测过程,并使其能够在当前没有资源泄漏检测工具的 Golang 上工作。
- 高级源代码分析:提高泄漏识别的准确性,尤其是对于用户定义的资源类。
这些进步将进一步提高 FixrLeak 的有效性,使其能够应对更复杂的场景,并为大型代码库带来更大的价值。
结论
资源泄漏仍然是大型软件系统中长期存在的挑战,但生成式 AI 提供了一种强大的新方法来应对这个问题。 FixrLeak 结合了 GenAI 和 AST 级别分析,弥合了检测和解决之间的差距,提供准确高效的修复,同时提高开发人员的生产力。 通过解决复杂的构建系统等实际挑战,FixrLeak 增强了 Uber 的 Java 代码库中的代码质量和可靠性,为软件工程中 AI 驱动的自动化树立了先例。
对于面临类似挑战的组织,FixrLeak 提供了以下关键要点:
- 优先考虑结构化代码分析:基于 AST 的技术有助于确保修复是安全且具有上下文感知能力的。
- 自动化有针对性的修复:首先关注范围明确、高置信度的修复,以最大限度地提高成功率。
- 负责任地集成 AI:通过严格的测试和代码审查流程来验证 AI 生成的代码。
虽然 FixrLeak 目前部署在 Uber,但其背后的原则——将静态分析与 GenAI 相结合——可以应用于其他大型系统。 寻求自动化代码质量改进的公司可以探索使用 AI 辅助代码修复、AST 分析和结构化 prompt 工程的类似技术。
本博客开启了 Programming Systems 团队关于利用 GenAI 解决软件工程挑战的一系列文章。 请继续关注下一篇文章,我们将探讨 GenAI 如何自动修复 Golang 中的数据竞争。
致谢
我们要感谢 Jens Palsberg 围绕资源泄漏进行的几项技术讨论。
封面照片归属:”BerwickDam01” by Korona Lacasse. is licensed under CC BY 2.0.
OpenAI ® 及其徽标是 OpenAI® 的注册商标。
Oracle、Java、MySQL 和 NetSuite 是 Oracle 和/或其关联公司的注册商标。 其他名称可能是其各自所有者的商标。
SONAR、SONARSOURCE、SONARQUBE 和 CLEAN AS YOU CODE 是 SonarSource SA 的商标。
Chris Zhang
Chris Zhang 是 Uber Programming System 团队的软件工程师。 他的研究兴趣包括计算机体系结构、编译器、操作系统和微服务。
Akshay Utture
Akshay Utture 是 Uber Programming Systems 组的软件工程师。 他目前正在使用 GenAI 自动化代码审查周期,但也对静态分析、编译器和程序修复感兴趣。
Manu Sridharan
Manu Sridharan,前 Uber 的高级工程师,现任加州大学河滨分校计算机科学与工程教授。 他的主要研究领域是编程语言和软件工程。
由 Chris Zhang、Akshay Utture、Manu Sridharan 发布
类别:
相关文章
Engineering, Backend, Data / ML将大规模交互式计算工作负载无中断地迁移到 Kubernetes8 May / Global
Engineering, Backend将 Uber 的计算平台迁移到 Kubernetes:技术之旅24 April / Global
Engineering, Backend, Data / ML, Uber AI使用上下文 Bandit 策略增强个性化 CRM 通信27 March / Global
Engineering, Backend使用 Profile-Guided Optimizations 自动化 Go 程序的效率13 March / Global
Engineering, Backend大规模采用 Arm:转型到多架构环境27 February / Global
最受欢迎
Engineering, Backend13 March / Global使用 Profile-Guided Optimizations 自动化 Go 程序的效率
Engineering, Backend, Data / ML, Uber AI27 March / Global使用上下文 Bandit 策略增强个性化 CRM 通信
Universities2 April / Global医学院如何通过 Uber 支持下一代医生
Engineering, Data / ML, Uber AI3 April / GlobalUber 在 Kubernetes 上的 Ray 之旅:Ray 设置
公司
产品
全球公民
旅行
© 2025 Uber Technologies Inc.
选择您的首选语言
注册成为车主
注册成为乘客
-
产品
-
公司
中文