JDK21 WARNING: A Java agent has been loaded dynamically

  • 背景
  • 解决
  • 经过
    • OpenJDK’s JEP 451: Balancing Serviceability and Integrity in JVM
  • 参考文章

背景

在做企业微信消息通知的时候,运行项目,出现该警告。

WARNING: A Java agent has been loaded dynamically (D:\maven-repository\net\bytebuddy\byte-buddy-agent\1.14.9\byte-buddy-agent-1.14.9.jar)WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warningWARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more informationWARNING: Dynamic loading of agents will be disallowed by default in a future release

解决

经过

查了一些资料,找到一篇英文的介绍,有想深入的小伙伴可以自己研究下。
这里贴到下面

OpenJDK’s JEP 451: Balancing Serviceability and Integrity in JVM

JEP 451, Prepare to Disallow the Dynamic Loading of Agents( 链接), has been completed from Target status for JDK 21. This JEP has evolved from its original intent to disallow the dynamic loading of agents into a running JVM by default to issue warnings when agents are dynamically loaded into a running JVM. The goals of this JEP include: reassessing the balance between serviceability and integrity; and ensuring that a majority of tools, which do not need to load agents dynamically, are unaffected.
(JEP 451,准备禁止代理的动态加载,已从 JDK 21 的目标状态完成。此 JEP 已从其最初的意图演变而来,即默认不允许将代理动态加载到正在运行的 JVM 中,而是在代理动态加载到正在运行的 JVM 时发出警告。该 JEP 的目标包括:重新评估可维护性和完整性之间的平衡;并确保大多数不需要动态加载代理的工具不受影响。)

The primary goal of this proposal is to prepare for a future release of the JDK that will, by default, disallow the loading of agents into a running JVM. This change is designed to reassess the balance between serviceability, which involves ad-hoc changes to running code, and integrity, which assumes that running code is not arbitrarily changed. It is important to note that the majority of tools, which do not need to load agents dynamically, will remain unaffected by this change.
(该提案的主要目标是为将来的 JDK 版本做准备,默认情况下,该版本将不允许将代理加载到正在运行的 JVM 中。此更改旨在重新评估可维护性(涉及对运行代码的临时更改)和完整性(假定运行代码未被任意更改)之间的平衡。需要注意的是,大多数不需要动态加载代理的工具将不受此更改的影响。)

In JDK 21, the dynamic loading of agents is allowed, but the JVM issues a warning when it occurs. For example:
(在 JDK 21 中,允许动态加载代理,但 JVM 会在发生时发出警告。例如)

WARNING: A Java agent has been loaded dynamically (D:\maven-repository\net\bytebuddy\byte-buddy-agent\1.14.9\byte-buddy-agent-1.14.9.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

To allow tools to load agents without warnings dynamically, developers must run with the -XX:+EnableDynamicAgentLoading option on the command line.
(要允许工具在没有警告的情况下动态加载代理,开发人员必须在命令行上使用 -XX:+EnableDynamicAgentLoading 选项运行。)

Agents in the Java platform are components that can alter the code of an application while it is running. They were introduced by the Java Platform Profiling Architecture in JDK 5 as a way for tools, notably profilers, to instrument classes. This means altering the code in a class so that it emits events to be consumed by a tool outside the application without otherwise changing the code’s behaviour.
(Java 平台中的代理是可以在应用程序运行时更改其代码的组件。它们是由 JDK 5 中的 Java 平台分析体系结构引入的,作为工具(尤其是分析器)检测类的一种方式。这意味着更改类中的代码,以便它发出事件以供应用程序外部的工具使用,而无需更改代码的行为。)

However, over time, advanced developers found use cases such as Aspect-Oriented Programming that change application behaviour in arbitrary ways. There is also nothing to stop an agent from altering code outside the application, such as code in the JDK itself. To ensure that the owner of an application approved the use of agents, JDK 5 required agents to be specified on the command line with the -javaagent or -agentlib options and loaded the agents immediately at startup. This represented an explicit grant of privileges by the application owner.
(然而,随着时间的流逝,高级开发人员发现了诸如面向方面的编程之类的用例,这些用例会以任意方式改变应用程序行为。也没有什么可以阻止代理更改应用程序外部的代码,例如 JDK 本身中的代码。为了确保应用程序的所有者批准使用代理,JDK 5 要求在命令行上使用 -javaagent 或 -agentlib 选项指定代理,并在启动时立即加载代理。这表示应用程序所有者显式授予特权。)

Serviceability is the ability of a system operator to monitor, observe, debug, and troubleshoot an application while it runs. The Java Platform’s excellent serviceability has long been a source of pride. To support serviceability tools, JDK 6 introduced the Attach API which is not part of the Java Platform but, rather, a JDK API supported for external use. It allows a tool launched with appropriate operating-system privileges to connect to a running JVM, either local or remote, and communicate with that JVM to observe and control its operation.
(可维护性是指系统操作员在应用程序运行时对其进行监视、观察、调试和故障排除的能力。长期以来,Java 平台出色的可维护性一直是我们引以为豪的源泉。为了支持可维护性工具,JDK 6 引入了 Attach API,它不是 Java 平台的一部分,而是支持外部使用的 JDK API。它允许以适当的操作系统权限启动的工具连接到正在运行的 JVM(本地或远程),并与该 JVM 通信以观察和控制其操作。)

However, despite a conceptual separation of concerns between libraries and tools, some libraries provide functionality that relies upon the code-altering superpower afforded to agents. For example, a mocking library might redefine application classes to bypass business-logic invariants, while a white-box testing library might redefine JDK classes so that reflection over private fields is always permitted.
(然而,尽管库和工具之间的关注点在概念上是分开的,但一些库提供的功能依赖于为代理提供的代码更改超级能力。例如,模拟库可能会重新定义应用程序类以绕过业务逻辑不变量,而白盒测试库可能会重新定义 JDK 类,以便始终允许对私有字段进行反射。)

Unfortunately, some libraries misuse dynamically loaded agents, leading to a loss of integrity. They use the Attach API to silently connect to the JVMs in which they run and load agents dynamically, in effect masquerading as serviceability tools. This misuse of dynamically loaded agents by libraries has led to the need for stronger measures to prevent such actions and maintain the integrity of the JVM.
(遗憾的是,某些库滥用了动态加载的代理,导致完整性丧失。它们使用 Attach API 以静默方式连接到运行它们的 JVM,并动态加载代理程序,实际上伪装成可维护性工具。库对动态加载代理的这种滥用导致需要采取更有力的措施来防止此类行为并维护 JVM 的完整性。)

The proposal aims to require the dynamic loading of agents to be approved by the application owner, moving the Java Platform closer to the long-term vision of integrity by default. In practical terms, the application owner will have to choose to allow the dynamic loading of agents via a command-line option.
(该提案旨在要求代理的动态加载必须得到应用程序所有者的批准,从而使 Java 平台更接近默认完整性的长期愿景。实际上,应用程序所有者必须选择允许通过命令行选项动态加载代理。)

The impact of this change will be mitigated by the fact that most modern server applications are designed with redundancy, so individual nodes can be restarted with the command-line option as needed. Special cases, such as a JVM that must never be stopped for maintenance, can typically be identified in advance so that the dynamic loading of agents can be enabled from the start.
(由于大多数现代服务器应用程序都设计有冗余,因此可以根据需要使用命令行选项重新启动单个节点,因此可以减轻此更改的影响。特殊情况,例如永远不能停止维护的 JVM,通常可以提前识别,以便从一开始就启用代理的动态加载。)

This change will allow the Java ecosystem to attain the vision of integrity by default without substantially constraining serviceability. It is a significant step towards ensuring the security and reliability of applications running on the JVM. The proposal is a clear indication of OpenJDK’s commitment to enhancing the integrity of the JVM and ensuring the secure operation of Java applications.
(这一变化将允许 Java 生态系统在默认情况下实现完整性的愿景,而不会严重限制可维护性。这是朝着确保在 JVM 上运行的应用程序的安全性和可靠性迈出的重要一步。该提案清楚地表明了 OpenJDK 致力于增强 JVM 的完整性并确保 Java 应用程序的安全运行。)

参考文章

  • https://www.infoq.com/news/2023/07/jep-451-balancing-serviceability/#:~:text=To%20allow%20tools%20to%20load%20agents%20without%20warnings,code%20of%20an%20application%20while%20it%20is%20running.