JEP 472:准备限制 JNI 使用
JEP 472 已被提升为“Proposed to Target”状态。该提案旨在对使用 Java 原生接口(JNI)发出警告,并调整外函数与内存(FFM)API 以发出一致的警告。这是为未来版本中通过统一限制 JNI 和 FFM API 来确保“默认完整性”做准备。该提案基于长期增强 Java 平台安全性和性能的努力,延续了 JEP 454(外函数与内存 API)、JEP 471(弃用 sun.misc.Unsafe
的内存访问方法)和 JEP 451(准备限制动态加载代理)的路线。主要目标是确保未来版本中任何使用 JNI 和 FFM API 的操作都需要在启动时获得开发者的明确批准。
JNI 的风险
JNI 自 JDK 1.1 引入,是 Java 代码与原生代码互操作的标准方式。然而,Java 代码与原生代码的交互可能会破坏应用程序和 Java 平台的完整性。例如,调用原生代码可能导致无法预测的问题,包括 JVM 崩溃,这些问题无法通过 Java 运行时处理或捕获异常。此外,通过直接字节缓冲区交换数据可能暴露 Java 代码于无效内存区域,导致未定义行为。原生代码还可以绕过 JVM 访问检查,修改字段或调用方法,可能违反 Java 代码的完整性。
分阶段限制 JNI 使用
JEP 472 提出了分阶段限制 JNI 使用的方案。最初,将对加载和链接原生库的操作发出警告,这些警告将统一应用于 JNI 和 FFM API。开发者可以通过在启动时为特定 Java 代码启用原生访问来避免警告。命令行选项 --enable-native-access=ALL-UNNAMED
可为类路径上的所有代码启用原生访问,开发者还可以为特定模块传递逗号分隔的模块名称列表。
受影响的代码
调用其他模块中声明的原生方法的代码不需要启用原生访问。但调用 System::loadLibrary
、System::load
、Runtime::loadLibrary
或 Runtime::load
,或声明原生方法的代码将受到原生访问限制的影响。如果从未启用原生访问的模块调用受限方法,JVM 会执行该方法但默认会发出警告,标识调用者。
控制原生访问限制的影响
开发者可以使用 --illegal-native-access
选项控制原生访问限制的影响,其模式包括:
allow
:允许受限操作而不发出警告。warn
:对模块中的首次非法原生访问发出警告(即将发布版本的默认值)。deny
:对每次非法原生访问操作抛出IllegalCallerException
(未来版本的默认值)。
长期目标是将默认行为过渡到 deny
,通过默认实施更严格的安全措施来增强 Java 平台的完整性和安全性。
开发者建议
开发者鼓励使用 deny
模式主动识别需要原生访问的代码并进行必要调整。此外,将引入新工具 jnativescan
以帮助识别使用 JNI 的库。
总结
JEP 472 标志着迈向更安全 Java 平台的重要一步。虽然向更严格的 JNI 限制过渡可能需要一些调整,但由此带来的安全性和完整性提升将是显著的。开发者可以通过为这些变化做好准备,确保平稳过渡并为更健壮的 Java 生态系统做出贡献。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。