Java 24 引入了新的 Java 原生接口(JNI)使用规则。从该版本开始,应用程序开发者必须在启动时明确启用 JNI,否则 Java 会打印如下警告信息:
WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by ... in module ... (file:...)
WARNING: Use --enable-native-access=... to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
新规则对桌面软件尤其有影响,因为主要的 UI 工具包依赖原生调用来实现渲染和操作系统集成等功能。
本文将讲解如何在使用 JxBrowser 以及主要 UI 工具包(JavaFX、SWT、Swing 和 Compose Desktop)的 Java 应用程序中启用 JNI 访问。
为什么要限制原生访问?
我们在 JNI 领域已有 15 年经验,因此理解为何现在必须引入新限制。将原生代码与 Java 结合从来都不是一件容易的事。Java 世界有自动内存管理和访问控制,而原生世界则更像是狂野的西部——充满口头约定,但缺乏严格规则。把两者结合,有了强大能力的同时,也伴随着重大风险。
问题主要在于内存安全。像 C 和 C++ 这样的原生语言不具备内存安全性:它们不会自动分配或释放内存,不会追踪指针是否仍然有效,也不强制数组边界检查。因此,内存管理完全依赖开发者,容易出现内存相关的 bug — 且非常棘手。
内存管理的 bug 很危险。在 JNI 代码中,它们可能破坏 Java 使用的内存并导致崩溃。
原提案作者提供了如下示例:一个原生函数可能会将 Java 的引用当作原始内存地址错误使用。写入该地址会破坏 JVM 内存,并在不可预测的时间导致崩溃:
void Java_pkg_C_setPointerToThree__J(jlong ptr) {
// 这将破坏 JVM 内存。
*(int*)ptr = 3;
}
另一个风险是原生代码可以在没有访问控制的情况下读取或修改 Java 对象的成员,包括改变 final 字段,甚至修改本应不可变的对象,如字符串。
访问控制和内存管理的缺失都会破坏 Java 程序的完整性。这就是为什么 Java 要收紧原生访问规则,最终目标是实现默认完整性。
从 Java 24 开始,应用程序开发者必须使用命令行参数 --enable-native-access
java --enable-native-access=module1,module2
下面,我们提供在 JavaFX、SWT、Compose Desktop 和 JxBrowser 中启用 JNI 的操作说明。
如何启用原生访问
原生访问对所有主要 UI 工具包都是必需的。没有它,它们无法创建窗口、处理缩放,甚至无法在屏幕上渲染组件。如果使用 JavaFX、SWT 或 Compose,需要启用原生访问以避免启动警告。
Swing 默认已启用原生访问,因为它属于 Java 核心库的一部分。
JxBrowser 的用户也需要启用原生访问。我们使用原生代码来处理一些关键任务,例如与 Chromium 的进程间通信以及与操作系统的交互。
JxBrowser
要启动使用 JxBrowser 的应用程序而不出现警告,请按以下方式配置 --enable-native-access
对于模块化应用程序,请将
jxbrowser模块加入列表:java --enable-native-access=jxbrowser,module1,module2对于非模块化应用程序,请使用
ALL-UNNAMED通配符:java --enable-native-access=ALL-UNNAMED
如果您在模块化 SWT 应用程序中使用 JxBrowser 8.12.0 或更早版本,请将 jxbrowser-swt
JavaFX
要启动 JavaFX 应用程序而不出现警告,您必须将必要的 JavaFX 模块添加到 --enable-native-access 命令行参数中。
每个 JavaFX 应用程序必需的模块是 javafx.graphics:
java --enable-native-access=jxbrowser,javafx.graphics
如果应用使用了 javafx.media 或 javafx.web,也必须将它们加入列表:
java --enable-native-access=jxbrowser,javafx.graphics,javafx.media,javafx.web
SWT
运行 SWT 或 Eclipse 应用程序而不出现警告,需要将 ALL-UNNAMED 设置到 --enable-native-access 参数中。
大多数 SWT 应用程序不使用模块路径,因为它们运行在 OSGi 环境中。因此使用 ALL-UNNAMED。如果在模块化应用中使用 SWT,需要为特定平台的模块启用原生访问:
java --enable-native-access=jxbrowser,org.eclipse.swt.win32.win32.x86_64
各平台对应的 SWT 模块列表:
org.eclipse.swt.win32.win32.x86_64org.eclipse.swt.win32.win32.aarch64org.eclipse.swt.linux.gtk.x86_64org.eclipse.swt.linux.gtk.aarch64org.eclipse.swt.cocoa.macosx.x86_64org.eclipse.swt.cocoa.macosx.aarch64
Compose Desktop
Compose Desktop 在操作系统交互和界面渲染上都依赖原生访问。它将操作系统交互委托给默认已启用原生访问的 AWT,而界面渲染则通过原生的 Skia 库完成。
目前,Compose 桌面尚未实现模块化。要运行 Compose 桌面应用而不出现警告,请将 ALL-UNNAMED 添加到 --enable-native-access
java --enable-native-access=ALL-UNNAMED
参考资料
发送中。。。
您的个人 JxBrowser 试用密钥和快速入门指南将在几分钟内发送至您的电子邮箱。
