OpenJDK JEP 451:在JVM中平衡可服务性和完整性
2023年07月27日 由 Samoyed 发表
688690
0
JEP 451“准备禁止代理的动态加载”已从 JDK 21的目标状态完成。该 JEP 的初衷是默认情况下不允许将代理动态加载到运行中的 JVM 中,现已演变为在将代理动态加载到运行中的 JVM 时发出警告。本 JEP 的目标包括:重新评估服务性和完整性之间的平衡;确保大多数不需要动态加载代理的工具不受影响。
本建议的主要目标是为 JDK 的未来版本做好准备,该版本将默认禁止在运行的 JVM 中加载代理。这一变更旨在重新评估服务性与完整性之间的平衡,前者涉及对运行代码的临时更改,而后者则假定运行代码不会被任意更改。需要注意的是,大多数不需要动态加载代理的工具都不会受到这一变更的影响。
在 JDK 21中,允许动态加载代理,但 JVM 会在出现这种情况时发出警告。例如:
WARNING: A {Java,JVM TI} agent has been loaded dynamically (file:/u/bob/agent.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
开发人员如果需要工具在没有警告的情况下动态加载代理,可以在命令行上使用-XX:+EnableDynamicAgentLoading选项运行。
Java 平台中的代理是可以在应用程序运行时更改其代码的组件。它们是由JDK 5中的Java平台分析体系结构引入的,作为工具(尤其是分析器)检测类的一种方式。这意味着改变类中的代码,使其发出事件供应用程序外的工具使用,而不改变代码的行为。
然而,随着时间的推移,高级开发人员发现了一些用例,如面向方面编程(Aspect-Oriented Programming),可以任意改变应用程序的行为。此外,也没有什么能阻止代理更改应用程序外部的代码,如 JDK 本身的代码。为了确保应用程序的所有者同意使用代理,JDK 5要求在命令行中使用-javaagent 或-agentlib 选项指定代理,并在启动时立即加载代理。这意味着应用程序所有者明确规定了权限。
可维护性是指系统操作员在应用程序运行时对其进行监控、观察、调试和故障排除的能力。长期以来,Java 平台出色的可维护性一直引以为傲。为了支持可维护性工具,JDK 6引入了 Attach API,该 API 并非 Java 平台的一部分,而是 JDK API 的一种外部使用支持。它允许以适当的操作系统权限启动的工具连接到运行中的本地或远程 JVM,并与该 JVM 通信以观察和控制其运行。
然而,尽管库和工具之间在概念上有所区别,但有些库提供的功能仍依赖于代理所拥有的代码修改超级能力。例如,模拟库可能会重新定义应用程序类,以绕过业务逻辑不变式,而白盒测试库可能会重新定义 JDK 类,以便始终允许对私有字段进行反射。
遗憾的是,有些库滥用动态加载代理,导致完整性丧失。它们使用 Attach API 悄无声息地连接到运行它们的 JVM 并动态加载代理,实际上是伪装成服务性工具。由于库滥用动态加载代理,因此需要采取更有力的措施来防止此类行为并维护 JVM 的完整性。
该提案旨在要求代理的动态加载必须得到应用程序所有者的批准,从而使 Java 平台更接近默认完整性的长期愿景。在实际操作中,应用程序所有者必须通过命令行选项选择是否允许动态加载代理。
由于大多数现代服务器应用程序的设计都具有冗余性,因此可以根据需要使用命令行选项重新启动单个节点,从而减轻了这一变化的影响。特殊情况(如绝不能停止维护的 JVM)通常可以提前确定,以便从一开始就启用代理的动态加载。
这一变化将使 Java 生态系统在不对可服务性造成实质性限制的情况下实现默认完整性的目的。这是朝着确保在 JVM 上运行的应用程序的安全性和可靠性迈出的重要一步。该建议清楚地表明 OpenJDK 致力于增强 JVM 的完整性并确保 Java 应用程序的安全运行。
来源:https://www.infoq.com/news/2023/07/jep-451-balancing-serviceability/