
Stripe 为 Java 代码库打造自动升级平台,持续跟进最新版本
来源标题:Modern Java at Stripe: Language upgrades as a service
Stripe 的 Java 团队构建了一个平台,让大型 JVM 代码库能持续升级到新版 Java,避免长期落后带来的性能和开发效率损失。该平台将语言升级做成可复用的服务,解决升级成本反复出现、大多数大型代码库难以跟上最新版本的问题。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
[B] 博客[E] 活动[D] 文档[Y] YouTube[G] GitHub[M] 聚会[U] 社区 Stripe 的现代 Java:将语言升级作为一种服务 /元数据 日期:2026.5.27 作者:Mahib Hosain、Cara Mecozzi 阅读时间:8 分钟 分类:工程 代理:为 LLM 复制、以 Markdown 查看 分享:Twitter/X、LinkedIn /文章 我们都清楚在企业科技公司工作的刻板印象:无休止的官僚流程,以及在多年前的语言版本上运行的庞大代码库。大多数组织都知道应该尽快现代化,但还没想清楚如何构建一条与大型代码库兼容的升级路径。升级的反复成本让大多数大型 JVM 代码库始终落后于最新的 Java 版本。
随着服务越来越落后于前沿,它们错失了多年来 JVM 改进所带来的成本节省和性能提升。开发者体验的下降是渐进的,以至于很难察觉,但随着时间的推移,缺乏新的语言特性会侵蚀产品交付的速度。在 Stripe,我们不愿接受这一点,因此我们投资于一种更好的方式来保持与时俱进。我们的 Java 团队打造了一个平台,能够持续演进而无需繁重的迁移,从根本上改变了我们的做法——从长达一个季度、往往无法完成的迁移项目,转变为持续的、自动化的更新。
从纸面上看,升级 Java 似乎很简单:只需更换工具链、更新几个依赖、修复少量编译器错误,然后继续。但实际上,有无数构建图约束需要应对。它们需要跨数百甚至数千个负责人进行协调的依赖和运行时变更。这种复杂性正是 Java 升级往往被搁置在积压列表中的原因。
以前,我们的 Java 迁移与其他大型组织非常相似。我们依赖定制的脚本、过时的清单数据,以及大量的人工推理。虽然已经出现了一些新颖的方法(例如通过 OpenRewrite 进行 AST 重写,PayPal、Apple 和 Walmart 都在使用这一工具),但现状从未转变为完全无需人工干预的方式。一次迁移会以一阵集中的关注开始,在构建图中容易的部分取得进展,然后一旦遇到最困难的部分就会放缓。
即使迁移本身是有用的,迁移所用的机制也无法在迁移后存续。这意味着每次新的 JDK 迁移都要从重新发现相同的事实开始: 我们一直在浪费时间一遍又一遍地解决同一个问题。我们想要停止反复运行漫长的迁移项目,转而构建一个持久且面向未来的升级流程。于是,AutoJDK 诞生了。
我们没有把每次 Java 升级当作一个反复出现的、长达一个季度的维护项目,而是构建了一个系统,它从实时构建图中持续计算升级资格,通过可审查的 PR 应用安全的迁移,利用 AI 修复某些类别的错误,并突出显示尚无法升级的代码的阻碍因素。
在深入了解 AutoJDK 工作原理的技术细节之前,有必要先理解 Java 代码库中版本升级的一些细微之处。
你可以在两个不同的 JDK 版本上编译 Java 代码和运行 Java 代码;但是,运行时版本必须大于或等于编译代码所用的版本。编译(升级语言级别)则受到更多限制——它涉及直接在我们的 JVM 代码库中大规模修改语言版本属性,并且要满足所有传递依赖和反向依赖(构建图中的父节点和子树)都能接受版本提升。
这意味着,除了一些注意事项外,将服务迁移到最新的 Java 运行时相对容易(这是合乎逻辑的第一步)。但是,为了应对升级语言版本带来的挑战,我们构建了一个内部系统,在我们的 JVM 单体仓库中自动升级 JDK 版本。
这让我们能够将运营模式从“我们本季度如何运行一次大规模的 Java 迁移?”转变为“我们今天升级了什么,还有什么仍然受阻?”
大型代码库中的语言版本管理问题,本质上关乎构建图结构和平台策略。如果 JDK 升级主要是一个构建图和兼容性问题,那么解决方案就应该从实时(最近缓存的)构建图开始。
我们的升级器是构建图驱动的。它使用图分析加上兼容性启发式方法,来确定哪些 Java 和 Scala 目标有资格升级。
资格判定不是基于一个扁平的目标列表。它会考虑以下因素: 一旦系统识别出符合条件的目标,就会在有界分区中生成 target_jdk 升级。
从运维角度来看,这意义重大。大规模的升级浪潮会造成合并冲突、让审查者不堪重负,并且难以安全地重新运行。我们希望即使系统在单体仓库规模下快速运行时,输出结果对人工来说仍然可读。
大规模语言升级中最困难的部分之一,是受阻的代码往往会变成口口相传的传说。每个人都知道某个子系统“很特殊”,或者某个库“仍然被固定”,但没有人能清晰、实时地了解有多少被阻塞、为什么被阻塞,以及怎样才能解除阻塞。
我们系统的一个重要部分就是以下方面的可见性: 有些升级失败确实是深层的兼容性问题,但另一些则更为机械,比如 CI 清理、明显的修复,或者为满足新工具链所需的小改动。
我们在补救循环中使用 AI 辅助,特别是针对那些可修复的失败类别,否则它们会产生大量的人工清理工作。Stripe 的 Minions 非常适合这项任务,因为它们可以修复小故障,并在沙箱中使用全新的 git 检出完成工作。
Minions 用于直接从 Slack 轻松启动升级: 注意:Zoolander 是我们的 JVM 代码库的名称。它因那部电影而得名,因为它最初承载着 Stripe 的(机器学习)模型。
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。