
《Sustainability for Java Developers》一本 Java 社区写给自己的可持续发展指南“Sustainable software development is not a single practice or technique—it is a way of seeing.”——本书结语谈到绿色软件、可持续发展很多 Java 程序员的第一反应是这和我写业务代码有什么关系这本书的回答是关系很大而且大部分事情从明天就能开始做。这篇文章会先介绍这本书的背景和结构再按章节分享书里的主要内容最后聊聊书中观点引出的一些我自己的想法。关于这本书《Sustainability for Java Developers: Towards an Understanding of Sustainable Java Software Development》由 foojay.ioFriends of OpenJDK社区发起。社区里越来越多人在讨论我们这个行业能为可持续做些什么于是大家决定一起写一本书。几个基本信息免费获取在 Leanpub 上免费提供 PDF、EPUB 等格式。持续更新2026 年 1 月首发2 月重写了架构一章3 月新增了 Docker 镜像瘦身的内容之后还会继续迭代。作者阵容12 位来自不同公司和国家的作者包括 A N M Bazlur Rahman、Frank Delporte、Geertjan Wielenga、Hanno Embregts、Jan Ouwens、Jan-Hendrik Kuperus、Ko Turk、Maarten Mulders、Markus Westergren、Simon Martinelli 等其中多位是 Java Champion。开放投稿只要和 Java 开发相关、对可持续有想法就可以加入 Foojay 的 Slack 参与贡献。作者们在前言里很坦诚他们不一定是这些话题的权威专家有些内容有明确的技术例子有些更多是态度上的转变。各章可以独立阅读所以这本书既能从头读到尾也能当作菜谱按需翻阅。全书结构章节作者主题引言 基础概念Jan-Hendrik Kuperus 等可持续的定义全书共用的 19 个概念第 1 章 Fair Trade SoftwareMaarten Mulders、Geertjan Wielenga开源生态的公平与正义第 2 章 Stopping the Data MadnessFrank Delporte数据格式与传输开销第 3 章 Impact of ArchitectureSimon Martinelli含 Jan Ouwens 一节架构如何决定资源消耗第 4 章 Career and WellbeingMarkus Westergren程序员的职业与身心可持续第 5 章 Java’s Evergreen AppealA N M Bazlur Rahman为什么 Java 是长期投资第 6 章 Simple things you can do right nowJan Ouwens、Ko Turk构建缓存、镜像瘦身等速效手段第 7 章 Java as a Scripting LanguageA N M Bazlur Rahman用 Java 25 写脚本结语Geertjan Wielenga可持续是一种看问题的方式可以看到这本书的覆盖面很广从开源伦理到 Dockerfile从架构设计到个人作息。这种跨度一开始可能让人意外但它正好体现了作者对可持续的理解。一、先重新定义可持续引言部分没有直接谈技术而是先回答什么是可持续。作者对比了维基百科和剑桥词典的定义然后给出了自己的版本Sustainability is the ability to create and maintain opportunities for human flourishing on a global scale, without discrimination.这个定义包含三层意思人能充分发挥潜力环境适宜居住经济是公平的。所以在这本书里环境只是可持续的一个维度开源维护者的处境、程序员的身心健康同样属于这个话题。引言里还有两个值得一提的内容数据数据中心和传输网络约占全球用电量的 2%–4%在 AI 竞赛的推动下这个比例到 2030 年可能大幅上升。关于AI 会解决气候问题作者打了个比方车正开向悬崖修车师傅还在修刹车你难道不先松一松油门给他争取点时间我的想法这个宽泛的定义有个实际好处它让不同角色都能找到切入点。做架构的可以关注资源消耗带团队的可以关注人的状态做技术选型的可以关注依赖的健康度。可持续不再只是运维或基础设施团队的事。二、开源依赖的公平贸易第一章是全书视角最独特的一章。作者用公平贸易咖啡做类比消费者愿意为公平贸易认证多付钱是因为不想参与对生产者的剥削。那软件的原材料是什么除了电力和硬件还有每个项目里成百上千个开源依赖。它们背后是真实的人很多人在业余时间无偿维护。书中描述了免费的悖论开源刻意不定价这是它能广泛传播的原因却也让维护者很难获得公平的回报。作者举了 Log4Shell 的例子漏洞爆发后一些大公司要求小型开源社区在 96 小时甚至更短时间内答复好赶上内部的报告期限却没有提供任何报酬。作者提出了公平贸易软件的四个方向公开透明地说明自己的软件供应链按获得的价值比例回馈尊重维护者不要求即时响应尊重他们设定边界的权利支持整个生态而不只是最显眼的明星项目。给组织的五条具体建议是设立开源支持预算、审计依赖、回馈上游、有重点地赞助、把项目的可持续性纳入技术选型。我的想法依赖审计和供应链安全其实是同一件事。很多公司已经在做 SBOM软件物料清单和漏洞扫描在这个基础上再加一列维护者是谁、是否有资金支持成本很低。用安全合规的名义申请开源赞助预算也比单纯谈公平更容易被管理层接受。书里提到有时自己写一个简单工具函数比引入一个明年可能被弃用的包更可持续。我很认同。每多一个依赖就多一个需要升级、需要关注漏洞的对象。引入依赖前多问一句真的需要吗是成本最低的供应链治理。对个人开发者来说最容易做的回馈是写一份可复现的 issue。这不花钱但能实实在在减轻维护者的负担。三、只有机器在读的数据为什么要人类可读第二章的作者 Frank Delporte 平时用 Java 控制电子元件他用一个很直观的例子说明数据格式的开销数码管上显示数字 5在电路里只需要 1 个字节0x6D。同样的信息换成常用的数据格式格式字符数压缩后HEX0x6D1-XML345150JSON250118YAML20299Protobuf2444两个细节值得注意XML 比原始数据大了 300 多倍对小数据压缩体积反而会变大。作者的核心问题是“既然只有计算机在读为什么要传输人类可读的数据” 需要排查时可以靠代码把字节解析成可读格式也可以用 Wireshark 这类工具抓包。书中还引用了 LinkedIn 的案例他们有超过 5 万个基于 JSON 的 API 端点在微服务之间改用 Protocol Buffers 后延迟最多降低了 60%。我的想法这个问题值得问但答案要分场景。适合换成二进制格式高频的内部服务调用、消息队列里的大量事件、物联网设备上报。在这些场景用 gRPC/Protobuf体积和序列化开销都能明显下降而且有 schema 约束类型更安全。继续用 JSON 也合理对外开放的 API、调用量很低的管理接口、需要和前端直接交互的接口。这些场景里可读性和生态兼容性带来的价值往往大于节省的那点带宽。换格式之前可以先做两件更便宜的事去掉响应里没人用的字段避免重复调用。这两点在第三章也有讨论。四、架构决定了可持续的天花板第三章由 Simon Martinelli 撰写2026 年 2 月做过一次大幅扩充是全书技术密度最高的一章。全章围绕一个批发企业的 ERP 系统展开核心观点是No amount of operational optimization can compensate for an architecture that requires all components to run all the time.如果架构要求所有组件一直运行运维层面再怎么优化也弥补不了。从需求阶段开始区分作者建议对每个模块问三个问题用户什么时候用中断会影响工作吗停机会让公司亏钱吗问完会发现ERP 里只有订单模块需要最高可用性和弹性产品和客户管理只在工作日办公时间使用仓储和运输从清晨用到下午财务模块每天甚至每月才出一次账单。Stop Chasing Nines这一节由 Jan Ouwens 撰写。他举了两个例子荷兰一些严格的新教组织包括报纸和网店周日会关闭网站乐高爱好者网站 BrickLink 每天有 10 分钟维护窗口。两者都提前告知用户运营得也都很好。他的建议是大多数应用 95% 的可用性就够了只要沟通清楚就能省掉冗余服务器和编排层的开销。架构上的具体做法默认使用模块化单体微服务的隐性成本包括网络调用和序列化、Kubernetes 控制面和 Sidecar、分布式追踪和日志、每个服务一个 JVM、每个服务一条流水线。作者推荐用 Spring Modulith在测试中强制校验模块边界ApplicationModules.of(ErpApplication.class).verify()等有明确证据时再拆出独立服务。优先异步通信A 同步调用 BB 就必须在 A 运行的所有时间里在线。改成事件驱动后订单模块把事件发到消息队列仓储模块早上 6 点上班时再消费。这就是 Holly Cummins 提出的LightSwitchOps不用的东西就关掉就像离开房间时随手关灯。用数据冗余换取解耦通过 ETL、CDC 或事件溯源让模块持有本地数据。ETL 可以安排在可再生能源占比更高的时段运行CDC 比轮询更省资源。高效使用资源缓存优先用 Caffeine 这类进程内缓存只有多实例必须共享状态时才用 RedisAPI 支持分页和字段选择避免 N1 调用100 个订单变成 101 次请求。弹性伸缩低频模块缩容到零核心模块合理配置资源。作者特别提醒自动伸缩往往扩容积极、缩容保守而从可持续的角度看缩容同样重要。章末留了一个问题很适合放进架构评审Does this design allow the system to use only the resources it needs, when it needs them, and nothing more?我的想法95% 可用性对面向消费者的核心业务很难直接推行但大多数公司都有大量内部系统、测试环境、预发环境和报表服务。从这些系统开始实践 LightSwitchOps几乎没有业务风险收益却很直接。缩容到零对 Java 一直不太友好主要卡在启动时间。好在 CDS、AOT 缓存、CRaC、GraalVM Native Image 这些技术已经比较成熟Java 服务按需启动不再是空想。这一章的思路和 DDD 里的核心域、支撑域划分很契合。不同的域本来就有不同的可用性要求只是我们过去很少把这个差异落实到部署和资源配置上。五、程序员自己也需要可持续第四章由 Markus Westergren 撰写是全书篇幅最长的一章。开头是一个很多人都经历过的场景作者连续盯了 14 个小时屏幕凌晨 3 点终于修好一个困扰了几周的竞态条件第二天同事 review 代码时在他的修复里发现了 3 个新 bug。这一章的主要内容代码质量和身心状态互相影响休息充足的开发者思路更清晰更注重细节技术决策也更稳妥反过来整洁的代码能降低认知负担减少救火。一旦进入负循环疲惫 → 代码质量差 → bug 多 → 压力大 → 更疲惫可以从技术和个人两头同时打破。健康债wellbeing debt我们定期重构代码来偿还技术债也需要定期重构自己的习惯来偿还健康债。现代 Java 降低认知负担lambda、Optional、模式匹配、虚拟线程都能让代码更简洁。作者的团队做过一次为期两周的重构休整把旧数据类改成 record用模式匹配简化控制流code review 变快了团队士气也明显回升。Inner Development Goals 框架从 Being、Relating、Thinking、Collaborating、Acting 五个维度规划成长。具体习惯20-20-20 护眼法则、专注时关闭通知、记技术日志、找导师也当导师、加入 JUG 等社区。行动计划按 30 天、3–6 个月、6 个月以上分阶段列出行动项并建议用习惯叠加把新习惯挂在已有习惯上。书中引用了一个数据62% 的科技从业者表示自己身心俱疲。我的想法这一章看起来和绿色软件关系最远其实是全书的地基。结语里有一句话说得很直接倦怠的开发者没有余力关心效率。一个天天被线上故障追着跑的团队不可能有时间去调 GC、瘦身镜像、重新评估 SLA。从这个角度看控制加班、保留还技术债的时间同样是可持续工程的一部分。作者讲的一段个人经历也很有参考价值他在职业中期想一口气学完云原生和微服务结果工作质量下降学得反而更慢。后来改成每天只学一小时在工作项目里实践新技术效果好得多。面对技术更新节奏比强度更重要。六、Java 本身就是一种长期投资第五章由 Bazlur Rahman 撰写。他的出发点是学习时间是开发者最稀缺的资源之一追逐一个两三年就过气的技术学习投入很可能变成沉没成本。他从几个方面说明 Java 为什么是长期投资持续演进从 lambda、Stream 到 record、模式匹配、虚拟线程、结构化并发再到分代 ZGC 和 AOT 缓存语言和 JVM 一直在进步适用面广企业系统、Android、大数据、金融交易、物联网都能用生态稳定JCP 机制加上 Oracle、Red Hat、Amazon、IBM、Azul 等多家公司共同支持过时得慢向后兼容做得扎实多年前写的代码往往改动很少就能运行离开几年再回来知识依然有用。我的想法这一章站在 Java 社区的立场难免偏向 Java读的时候要意识到这一点。但技术选型要考虑长期维护成本这个原则适用于任何技术栈。选型时除了比较性能和功能也值得评估这项技术五年后还有人维护吗团队换人后还招得到人吗七、把 Java 当脚本语言第七章同样由 Bazlur Rahman 撰写。Java 25 引入了 JEP 512紧凑源文件和实例 main 方法一个完整的程序只需要这样写voidmain(){IO.println(Hello, World!);}再加上单文件执行JEP 330、多文件执行JEP 458、模块导入JEP 511和 shebang 支持Java 写小工具已经不比 Bash 或 Python 麻烦。书中给出了文件处理、HTTP 请求、调用系统命令、JDBC 查询、JSON 处理借助 JBang 管理依赖等常见模式还建议团队建一个共享的脚本仓库。作者从可持续的角度给出的理由是代码寿命长为 Java 25 写的脚本在未来的版本上大概率还能运行不会出现 Python 2 到 3 那样的大规模断裂类型安全错误在运行前就能发现而不是脚本跑了几个小时才暴露执行高效JIT 编译后速度快任务 10 秒跑完而不是 100 秒CPU 就只做了十分之一的工作平滑扩展从单个文件长成多个文件再到引入 Maven都不需要重写逻辑。我的想法对短小、一次性的脚本来说JVM 的启动开销可能抵消 JIT 的优势Bash 依然更合适。但对于要长期维护、团队共享、逻辑稍复杂的运维工具Java 脚本确实是个好选择尤其是团队本来就以 Java 为主的时候不用再额外维护一套 Python 环境和依赖。八、马上就能做的几件小事第六章由 Jan Ouwens 和 Ko Turk 撰写是全书最适合直接动手的一章。作者引用 Holly Cummins 的观点只要能让应用跑得更快或者降低运行成本你大概率就是在减少碳排放。构建缓存Maven 第一次构建会下载整个互联网。CI 环境每次都是全新的这意味着每次提交都要重新下载一遍。在 GitHub Actions 里加一行配置就能解决-name:Set up JDKuses:actions/setup-javav5with:java-version:25distribution:temurincache:maven# 加这一行就够了更进一步可以启用 Gradle Build Cacheorg.gradle.cachingtrue或 Maven 的maven-build-cache-extension需要 Maven 3.9.1 及以上跳过没有变化的模块和测试还能配置远程缓存在团队内共享。作者特别提醒缓存配置很容易悄悄失效要定期确认它真的生效了。Docker 镜像瘦身书中用一个 Hello World 程序演示了镜像一步步压缩的过程方案镜像大小直接用 Maven 镜像构建并运行约 500 MB多阶段构建397 MB换成eclipse-temurin:25-jre-alpine227 MBjdeps jlink 裁剪运行时124 MBGraalVM Native Image94.3 MBNative Image 静态链接 FROM scratch13.4 MB镜像变小存储、备份和传输的开销都会下降去掉 shell 和包管理器攻击面也更小。作者同时提醒了几个现实问题原生二进制和平台绑定反射较多的框架用 jlink 需要额外配置如果线上需要进容器调试就不能只放一个二进制文件在公司内部统一基础镜像可能比各项目各自追求最小镜像更划算因为共享镜像只需下载一次、修补一次。这一节的最后一句话很适合贴在工位上Whatever you do, don’t ship a 500MB Docker image for a 2.6kB jar file.给慈善机构捐款这条建议有点出人意料。作者引用 William MacAskill 在《What We Owe the Future》中的观点开发者的收入通常高于平均水平但缺少种树、游说、诉讼所需的时间和专业知识慈善机构恰好相反。捐款能借助慈善机构的规模效应产生个人难以达到的影响。贯穿全书的几个概念书的开头有一章基础概念列了 19 个概念后面各章会反复引用。其中几个特别值得了解5R 原则Refuse、Reduce、Reuse、Repurpose、Recycle。顺序很重要拒绝不必要的工作比事后回收它产生的浪费有效得多。放到软件里第一步就是不做没人用的功能。说不的能力对范围蔓延、不必要的复杂度、永远在线说不。先思考再编码最可持续的代码是根本不需要写的那一行。O(n) 和 O(n²) 在开发环境里感觉不出差别到了生产规模就是巨大的浪费。边际收益的数学1% 的优化乘以每天数百万次执行、上千个应用和好几年的运行时间就是可观的节约。反过来一个被广泛使用的库里的小低效浪费的能源可能比任何一个开发者一辈子能省下的都多。云的悖论云让开一台服务器感觉毫无分量无限容量的错觉会鼓励过度配置。要把资源当作稀缺的即使它看起来是无限的。数据是有重量的每一封归档邮件、每一个被遗忘的 Docker 镜像、每一份多余的备份都在消耗存储和能源。集体行动放大影响删除自己的旧邮件远不如推动团队和组织一起改变。测量是优化的基础我们对延迟和错误率追踪得一丝不苟却很少测量能耗。被测量、被看见的东西才会被管理。延伸想法书里没展开的几个方向这本书提出了很多好问题也有几个方向点到为止。下面是我顺着书里的思路想到的一些补充。1. 测量需要具体的工具书中反复强调测量是优化的基础但没有具体介绍能耗测量工具。对 Java 开发者来说可以从这几个层次入手应用层JDK Flight RecorderJFR、async-profiler用来找出 CPU 热点、内存分配和 GC 压力。它们不直接给出能耗数据但 CPU 和内存是能耗最主要的来源。能耗估算JoularJX 这类 Java agent 可以把能耗估算到方法级别Kubernetes 环境可以用 Kepler 估算 Pod 的能耗。云账单与碳排放主流云厂商都提供碳足迹面板开源的 Cloud Carbon Footprint 可以汇总多云数据。统一口径Green Software Foundation 的 SCISoftware Carbon Intensity规范提供了单位功能碳排放的计算方法适合用来对比优化前后的效果。我的建议是先别追求精确的碳排放数字。先用 JFR 和云账单建立资源使用的基线就已经能发现大部分浪费。2. 成本是推动落地最好的抓手书里有一个可持续的商业论证概念高效的代码运行更快、成本更低维护良好的系统需要更少的紧急干预。Jan Ouwens 在Stop Chasing Nines里也建议算出降低 SLA 能省多少钱这可能是说服决策者最有效的方法。在大多数团队里单纯谈环保很难排进迭代计划但谈每月能省多少云费用就容易得多。可持续工程和 FinOps 在实践中高度重合关停闲置环境、右调资源配额、精简镜像既降低成本也减少能耗。把两者放在一起推进阻力会小很多。3. AI 编程时代先思考再编码更重要书里提到最可持续的代码是根本不需要写的那一行。在 AI 编程助手普及之后这句话有了新的含义生成代码的成本越来越低代码量很容易膨胀而每一行代码都需要被审查、测试、运行和维护。我的看法是AI 让能不能写出来不再是瓶颈该不该写和写多少变得更关键。5R 原则里的 Refuse 和 Reduce在这个时代反而更值得强调。4. 可持续是一个团队习惯书里的建议大多是一次性动作比如加一行缓存配置、改一次 Dockerfile。但缓存会悄悄失效镜像会慢慢变大测试环境会在某次需求后重新开着过夜。要让效果持续最好把它变成流程的一部分在架构评审模板里加一项资源与可用性需求在 CI 里加入镜像大小检查超过阈值就告警定期比如每季度回顾云资源使用和依赖健康度在技术分享里固定留一个可持续话题。这本书适合谁读刚接触绿色软件的 Java 开发者先读引言、基础概念和第 6 章能快速建立整体认识并马上找到可以动手的地方。架构师和技术负责人第 3 章值得精读它提供了一套从需求分析到部署伸缩的完整思路。团队管理者第 1 章和第 4 章分别讨论了开源依赖治理和团队的可持续状态都和管理决策直接相关。对 Java 新特性感兴趣的开发者第 7 章是 Java 25 脚本能力的实用教程。需要注意的是这本书由多位作者合写各章风格和深度不太一样。第 3 章、第 6 章的技术细节很扎实第 4 章更偏个人成长第 5 章则带有比较明显的社区立场。按需挑章节阅读体验会更好。结语这本书没有给出一套标准答案它更想改变我们看问题的方式。结语里说贯穿全书的主线是有意识地做选择而不是把浪费当作默认。这种浪费可能是一个 500 MB 的镜像、一个整夜空转的财务模块、一段只有机器在读的 XML也可能是一个被要求 96 小时内答复的开源志愿者或者一个凌晨 3 点还在盯着屏幕的开发者。书的最后一句话是That is what sustainability means in practice: not perfection, but continuous, conscientious improvement—one line of code at a time.不追求完美只是持续、认真地改进一行代码接一行代码。如果你对这个话题感兴趣这本书免费、可以按章阅读也欢迎加入 Foojay 社区参与后续内容的贡献。参考Sustainability for Java DevelopersLeanpubSustainability for Java Developersfoojay.io