Java9 中的开放模块是什么,如何使用?

What is an open module in Java 9 and how do I use it?

前面有 open 关键字和没有关键字的模块有什么区别?例如:

open module foo {
}

module foo {
}

为了提供对模块的反射访问,Java 9 引入了 open 关键字。

您可以在模块声明中使用 open 关键字创建一个开放模块。

open 模块向其他模块授予对其所有包的反射访问权限。

比如你想使用一些严重依赖反射的框架,比如Spring、Hibernate等,你可以使用这个关键字为其启用反射访问。

您可以通过在包声明中使用 opens 语句来为模块的指定包启用反射访问:

module foo {
    opens com.example.bar;
}

或者在模块声明中使用 open 关键字:

open module foo {
}

但请记住,您不能将它们组合在一起:

open module foo {
    opens com.example.bar;
}

结果出现编译时错误。

希望对您有所帮助。

有关指令的一些背景知识。 Breaking encapsulation 部分中的 Module System 状态

It is sometimes necessary to violate the access-control boundaries defined by the module system, and enforced by the compiler and virtual machine, in order to allow one module to access some of the unexported types of another module. This may be desirable in order to, e.g., enable white-box testing of internal types, or to expose unsupported internal APIs to code that has come to depend on them. The --add-exports option can be used, at both compile time and run time, to do this.

命令行选项相当于例如:-

module java.logging {
    exports java.util.logging;
}

--add-exports 选项允许访问指定包的 public 类型。


尽管此后,

It is sometimes necessary to go further and enable access to all non-public elements via the setAccessible method of the core reflection API. The --add-opens option can be used, at runtime, to do this.

此命令行选项等效于例如:-

module jdk.unsupported  {
   opens sun.misc; 
}

相比之下,普通的命名模块是用模块声明显式定义的:-

module foo { }

这些被称为 explicit modules。显式模块可以在包上使用指令,例如 export/open 包,以提供对其各自 public 成员和 类.

的反射访问

另一方面,OPEN模块是

module that does not declare any open packages but the resulting module is treated as if all packages are open.

这样它就可以在运行时授予对所有模块包中类型的访问权限,就好像所有包都已导出一样,这意味着字节码或反射可用于访问每个包的类 或所有包中的成员setAccessibleMethodHandles.privateLookupIn的反射API允许深度反射,所以简而言之你可以反射所有成员所有包中的所有 类。这也很好地解释了编译器不允许

的原因

假设 'foo' 有两个包,com.example 和 com.example.bar

module foo {
    opens com.example;
}

上面的模块声明允许在运行时对包内 'com.example' 包内的类型进行反射访问。

但是'com.example'在外部编译时将不可见。

open module foo {
}

这意味着,它隐式打开模块中的所有包以供运行时反射访问。

以上模块声明等同于以下内容,

module foo {
    opens com.example;
    opens com.example.bar;
}