Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过反射绕过Java模块化_Java_Java Module_Java Platform Module System - Fatal编程技术网

通过反射绕过Java模块化

通过反射绕过Java模块化,java,java-module,java-platform-module-system,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

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模块系统中有两种可读性:和。在模块系统的第一个版本中(在Java 9发布之前的开发过程中),这两种类型是相同的。因此,您的第二个示例确实会失败并出现错误,因为从
m1
java.xml
没有
requires
子句。后来修订了该政策,放宽了关于反射可读性的规则,因为这种严格的政策在许多严重依赖反射的框架(例如Spring)中没有发挥好作用。现在,模块系统并不要求反射的可读性边缘(但目标类型仍然必须导出,定义模块必须在模块图中)

5.2反射可读性

为了使提供者类能够访问我们需要创建的框架 提供程序的模块可被框架的模块读取。我们可以 要求每个框架明确增加必要的可读性 在运行时将边缘添加到模块图,如本文档的早期版本中所示 但经验表明,这种方法既麻烦又费时 移民障碍

因此,我们修改反射API只是为了假设 任何反映某种类型的代码都位于可以读取 定义该类型的模块。这将启用上述示例,并且 其他类似的代码,可以不做更改地工作。这种方法并不适用 弱化强封装:公共类型必须仍在 导出的包,以便从其定义外部访问 模块,无论是来自编译代码还是通过反射