Java –add-opens java.base/java.lang=ALL-UNNAMED

在Java 9及以后的版本中,引入了模块化系统,它允许将代码和资源划分为多个模块以提高代码的可维护性和安全性。然而,由于模块的隔离性,某些代码可能无法在模块之间进行正常的交互。这时,我们可以使用Java--add-opens选项来解决此类问题。

什么是--add-opens选项?

--add-opens是Java 9引入的一个命令行选项,它允许我们在模块之间打开指定的包,以便其他模块可以访问这些包中的类和成员。特别地,--add-opens选项用于在指定的模块中打开指定的包,并将其对所有模块的访问权限设置为“ALL-UNNAMED”,这意味着所有模块都可以访问这些包。

如何使用--add-opens选项?

我们通过一个简单的代码示例来演示如何使用--add-opens选项。假设我们有两个模块:com.example.moduleAcom.example.moduleB,并且moduleA需要访问moduleB中的一个受限包com.example.moduleB.internal。在正常情况下,由于模块的隔离性,moduleA无法访问com.example.moduleB.internal包中的类和成员。

让我们先来创建moduleB模块。我们创建一个名为com.example.moduleB的文件夹,并在该文件夹中创建一个模块描述文件module-info.java,其内容如下:

module com.example.moduleB {exports com.example.moduleB; // 公开com.example.moduleB包// 不公开com.example.moduleB.internal包}

接下来,我们在com.example.moduleB包中创建一个简单的类MyClass,其代码如下:

package com.example.moduleB;public class MyClass {public void sayHello() {System.out.println("Hello from moduleB!");}}

现在,我们创建moduleA模块。同样地,我们创建一个名为com.example.moduleA的文件夹,并在该文件夹中创建一个模块描述文件module-info.java,其内容如下:

module com.example.moduleA {// 不公开任何包}

我们在com.example.moduleA模块中创建一个类Main,尝试访问moduleB模块中的MyClass类,其代码如下:

package com.example.moduleA;import com.example.moduleB.MyClass;public class Main {public static void main(String[] args) {MyClass myClass = new MyClass();myClass.sayHello();}}

如果我们尝试编译并运行上述代码,将会得到一个编译错误,提示无法访问com.example.moduleB.internal包。

为了解决这个问题,我们可以使用--add-opens选项。我们可以在运行moduleA模块时,使用以下命令行参数来打开moduleB模块中的com.example.moduleB.internal包:

java --add-opens com.example.moduleB/com.example.moduleB.internal=com.example.moduleA -m com.example.moduleA/com.example.moduleA.Main

通过上述命令行参数,我们将moduleB模块中的com.example.moduleB.internal包对moduleA模块的访问权限设置为“ALL-UNNAMED”。现在,我们再次编译并运行Main类,将会成功输出Hello from moduleB!

总结

--add-opens选项是Java 9引入的一个命令行选项,用于打开模块之间的包,以便其他模块可以访问这些包中的类和成员。通过使用--add-opens选项,我们可以解决由于模块的隔离性而导致的访问限制问题。但是,应该注意的是,--add-opens选项可能会降低代码的安全性,因为它打开了