java - 通过反射绕过 Java 模块化

标签 java java-module java-platform-module-system

Java 模块系统是否应该阻止模块通过反射访问其他模块,而不声明正确的模块依赖关系?

例如,在编译这个 hello world Java 11 类时,它从另一个模块调用类,正如预期的那样,它不会编译,因为缺少对 java.xml 的依赖:

module m1 {}

package p1;
public class C1 {
    public static void main(String[] args) throws Exception {
        System.out.println(javax.xml.XMLConstants.XML_NS_URI);
    }
}

将模块依赖项添加到 java.xml 后,它会按预期编译并运行。

但是,这个类:

module m1 {}

package p1;
public class C1 {
    public static void main(String[] args) throws Exception {
       System.out.println(Class.forName("javax.xml.XMLConstants").getField("XML_NS_URI").get(null));
    }
}

运行并打印结果,无需声明对 java.xml 的模块依赖:

java -version
openjdk version "11.0.2" 2019-01-15

java -p bin -m m1/p1.C1
http://www.w3.org/XML/1998/namespace

我们能够有效地绕过 Java 模块化。

这适用于任何模块到任何其他已解析的模块。

这怎么可能?模块系统应该防止这种情况发生吗?

最佳答案

Java模块系统中有两种可读性: static readabilityreflective readability 。在模块系统的第一个版本中(在 Java 9 中发布之前的开发过程中),这两种类型是相同的。因此,您的第二个示例确实会失败并出现错误,因为从 m1java.xml 没有 requires 子句。后来这个政策被修改,反射可读性的规则被放宽,因为这种严格的政策在许多严重依赖反射的框架(例如 Spring)中表现不佳。现在,模块系统不强制要求反射的可读性边缘(但仍然必须导出目标类型,并且定义模块必须位于模块图中)。

5.2 Reflective readability

...

To make the provider class accessible to the framework we need to make the provider’s module readable by the framework’s module. We could mandate that every framework explicitly add the necessary readability edge to the module graph at run time, as in an earlier version of this document, but experience showed that approach to be cumbersome and a barrier to migration.

We therefore, instead, revise the reflection API simply to assume that any code that reflects upon some type is in a module that can read the module that defines that type. This enables the above example, and other code like it, to work without change. This approach does not weaken strong encapsulation: A public type must still be in an exported package in order to be accessed from outside its defining module, whether from compiled code or via reflection.

关于java - 通过反射绕过 Java 模块化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58819123/

相关文章:

java - java 是否将字符串定义为以 null 结尾?

java - 在Java中的多个整数HashSet中查找所有没有重复的元素

java - 使用 Java EE API 替换已弃用的 JPMS 模块

java - 无法使用 JNA : com. sun.jna.Library 不可访问

java - 如何使用第三方库(jar 文件)运行 Java 模块类(java 9 jigsaw 项目)?

java - 在 Java 中同时对三个 ArrayLists 进行排序的最有效方法是什么

java - JFreeChart:TimeSeries 图表上的多个时间序列显示不正确

java - 模块声明中的 requires 和 requires static 有什么区别

java - Java 包和模块的允许名称

java - JDK9中如何解决java.lang.module.ResolutionException