Java 9 中有很多关于非法反射访问的问题。
我发现了很多关于解决错误消息的讨论,但我很想知道非法反射访问实际上是什么。
所以我的问题是:
什么定义了非法反射访问以及什么情况会触发警告?
我已经收集到它与 Java 9 中引入的封装原则有关,但我找不到关于它们如何结合在一起、什么触发警告以及在什么情况下的解释。
原文由 Tschallacka 发布,翻译遵循 CC BY-SA 4.0 许可协议
Java 9 中有很多关于非法反射访问的问题。
我发现了很多关于解决错误消息的讨论,但我很想知道非法反射访问实际上是什么。
所以我的问题是:
什么定义了非法反射访问以及什么情况会触发警告?
我已经收集到它与 Java 9 中引入的封装原则有关,但我找不到关于它们如何结合在一起、什么触发警告以及在什么情况下的解释。
原文由 Tschallacka 发布,翻译遵循 CC BY-SA 4.0 许可协议
我发现了一篇关于 Java 9 模块系统的 Oracle 文章
默认情况下,模块中的类型不能被其他模块访问,除非它是公共类型并且您导出它的包。您只公开要公开的包。对于 Java 9,这也适用于反射。
正如 https://stackoverflow.com/a/50251958/134894 中所指出的,JDK8 和 JDK9 的 AccessibleObject#setAccessible
之间的差异具有指导意义。具体来说,JDK9增加了
如果满足以下任何条件,则类 C 中的调用者可以使用此方法来启用对声明类 D 的成员的访问:
- C和D在同一个模块中。
- 成员是公共的,D 在包含 D 的模块导出到至少包含 C 的模块的包中是公共的。
- 该成员是受保护的静态成员,D 在包含 D 的模块导出到至少包含 C 的模块的包中是公共的,并且 C 是 D 的子类。
- D 在包含 D 的模块至少对包含 C 的模块打开的包中。未命名和打开模块中的所有包都对所有模块打开,因此当 D 在未命名或打开模块中时,此方法总是成功。
这突出了模块及其导出的重要性(在 Java 9 中)
原文由 ptomli 发布,翻译遵循 CC BY-SA 4.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答6k 阅读
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
2 回答1.5k 阅读✓ 已解决
1 回答490 阅读
2 回答3.4k 阅读✓ 已解决
2 回答779 阅读✓ 已解决
1 回答1.3k 阅读
除了了解模块及其各自包之间的访问之外。我相信它的症结在于 模块系统#Relaxed-strong-encapsulation ,我会挑选其中的相关部分来尝试回答这个问题。
为了帮助迁移到 Java-9,可以放松对模块的强封装。
实现可以提供 _静态访问_,即通过编译的字节码。
可以提供一种方法来调用其运行时系统,其中一个或多个模块的一个或多个包对 所有未命名模块 中的代码开放,即类路径上的代码。如果以这种方式调用运行时系统,并且如果这样做,反射 API 的某些调用会成功,否则它们会失败。
在这种情况下,您实际上最终进行了 “非法” 的 _反射访问_,因为在纯模块化世界中,您不应该进行此类访问。
这种封装的放松在运行时由一个新的启动器选项
--illegal-access
在 Java9 中默认等于permit
。permit
模式确保这些模式可配置为值
debug
(每次此类访问的消息和堆栈跟踪)、warn
(每次此类访问的消息)和deny
此类操作)。在应用程序上调试和修复的几件事是:-
--illegal-access=deny
运行它,以了解并避免在没有包含此类指令(opens
)的模块声明或显式使用--add-opens
的情况下从一个模块 打开 包到另一个模块---
虚拟机参数。--jdk-internals
选项的jdeps
工具识别从编译代码到 JDK 内部 API 的静态引用此类示例警告的问题: = JDK9:发生了非法反射访问操作。 org.python.core.PySystemState
最后也是重要的一点,在尝试确保您不会面临此类警告并且未来安全时,您需要做的就是确保您的模块不会进行那些非法的反射访问。 :)