通过反射绕过Java模块化
Java模块系统是否应该阻止模块通过反射访问其他模块,而不声明正确的模块依赖关系 例如,编译这个hello world Java 11类时,它从另一个模块调用一个类,但正如预期的那样,它不会编译,因为缺少对通过反射绕过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.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只是为了假设
任何反映某种类型的代码都位于可以读取
定义该类型的模块。这将启用上述示例,并且
其他类似的代码,可以不做更改地工作。这种方法并不适用
弱化强封装:公共类型必须仍在
导出的包,以便从其定义外部访问
模块,无论是来自编译代码还是通过反射