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 指定需要 JNI 访问的模块:

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 模块添加到列表中。在 Eclipse RCP 等 OSGi 环境中,此操作不是必需的,因为它们不使用 Java 模块。

JavaFX 

要启动 JavaFX 应用程序而不出现警告,您必须将必要的 JavaFX 模块添加到 --enable-native-access 命令行参数中。

每个 JavaFX 应用程序必需的模块是 javafx.graphics

java --enable-native-access=jxbrowser,javafx.graphics

如果应用使用了 javafx.mediajavafx.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_64
  • org.eclipse.swt.win32.win32.aarch64
  • org.eclipse.swt.linux.gtk.x86_64
  • org.eclipse.swt.linux.gtk.aarch64
  • org.eclipse.swt.cocoa.macosx.x86_64
  • org.eclipse.swt.cocoa.macosx.aarch64

Compose Desktop 

Compose Desktop 在操作系统交互和界面渲染上都依赖原生访问。它将操作系统交互委托给默认已启用原生访问的 AWT,而界面渲染则通过原生的 Skia 库完成。

目前,Compose 桌面尚未实现模块化。要运行 Compose 桌面应用而不出现警告,请将 ALL-UNNAMED 添加到 --enable-native-access 命令行参数:

java --enable-native-access=ALL-UNNAMED

参考资料 

Spinner

发送中。。。

抱歉,发送中断

请再次尝试,如果问题仍然存在,请联系我们 info@teamdev.com.

阅读并同意条款以继续。

您的个人 JxBrowser 试用密钥和快速入门指南将在几分钟内发送至您的电子邮箱。