1. setAccessible()
在未来会被阻止吗?
不,AccessibleObject#setAccessible(boolean)
既没有被弃用,也没有我知道的计划将其弃用。
您看到的警告与此方法相关,但并非直接相关。 Java 9中引入的Java平台模块系统在编译时和运行时(即反射)都增加了更强的封装性。 运行时规则由#setAccessible(boolean)
记录:
如果以下任何一项成立,则调用类 C
可以使用此方法来启用对声明类 D
成员的访问权限:
C
和 D
在同一个模块中。
- 成员是公共的,
D
在导出至至少包含 C
的模块的包中是公共的。
- 成员是受保护的静态成员,
D
在导出至至少包含 C
的模块的包中是公共的,且 C
是 D
的子类。
D
在导出至至少包含 C
的模块的包中。所有未命名和开放模块中的所有包都对所有模块开放,因此当 D
在未命名或开放模块中时,此方法始终成功。
无法使用此方法来启用对私有成员、默认(包)访问权限的成员、受保护的实例成员或在声明类与调用者不在同一模块且包含声明类的包未向调用者的模块开放的受保护构造函数的访问权限。
这是一个重大变更,与Java 8不同的是,反射可以自由地访问它想要访问的任何内容(假设没有
SecurityManager
)。 这种破坏性的变化是一个问题,因为Java以向后兼容为傲。 为了给库和框架足够的时间进行迁移,他们放宽了特定情况下的强封装(见下文)。
2. 这个功能的官方参考文档(将来会被弃用)在哪里?
您看到的警告与--illegal-access
选项有关,该选项在java
工具规范中有记录:
当在运行时存在时,
--illegal-access=
需要一个关键字
参数来指定操作模式:
注意: 该选项将在未来一个版本中被移除。
permit
:该模式打开运行时镜像中每个模块中的每个包以允许所有未命名模块(例如类路径上的代码)中的代码,如果该包存在于JDK 8中 [强调添加]。这使得通过平台的各种反射API进行静态访问(例如通过编译后的字节码和深度反射访问)成为可能。对任何此类包的第一个反射访问操作会导致发出警告。但是,在第一次出现后不会发出警告。这个单独的警告描述了如何启用进一步的警告。该模式是当前JDK的默认模式,但在未来版本中将更改 [强调添加]。
warn
:该模式与permit相同,只是对于每个非法反射访问操作都会发出警告消息。
debug
:该模式与warn相同,只是对于每个非法反射访问操作都会发出警告消息和堆栈跟踪。
deny
:该模式禁用所有非法访问操作,除了由其他命令行选项启用的操作,例如--add-opens
。 在未来版本中,该模式将成为默认模式 [强调添加]。
默认模式--illegal-access=permit
旨在使您意识到类路径上的代码至少一次反射访问任何JDK内部API。要了解所有这些访问,可以使用warn或debug模式。对于需要非法访问的每个类库或框架,您有两个选择:
如果必须继续使用需要非法访问的组件,则可以使用一个或多个--add-opens
选项来打开只需要访问的那些内部包,以消除警告消息。
为了验证应用程序已准备好使用JDK的未来版本,请运行--illegal-access=deny
以及任何必要的--add-opens
选项。任何剩余的非法访问错误很可能是由编译代码对JDK内部API的静态引用所致。您可以通过将jdeps
工具与--jdk-internals
选项一起运行来识别它们。出于性能原因,当前的JDK不会针对非法的静态访问操作发出警告。
总结强调部分:
- 默认模式为
permit
。
- 这允许在未命名模块(即类路径)中的代码访问运行时映像(即JDK)中模块内的成员,即使那些成员在非导出/非打开包中(只要这些包存在于JDK 8中)。
- 最终默认模式将变为
deny
。
- 此时没有经过适当迁移的任何代码将停止工作。这就是为什么您看到警告 - 他们希望您解决问题(如果是您自己的代码,则自己解决;如果是第三方代码,则提交错误报告)。
--illegal-access
选项本身最终将被完全删除。
这些更改将在哪个版本中发生...我不知道。然而,在默认模式变为deny
之后,--illegal-access
选项可能会在一两个版本之后被删除。
更新(2021年5月31日)
JEP 396: Strongly Encapsulate JDK Internals by Default已在Java 16中发布,并将默认模式设置为deny
。 --illegal-access
选项仍然存在。
JEP 403: Strongly Encapsulate JDK Internals目前针对Java 17进行了优化。这将使permit
,warn
和debug
模式失效,并且尝试使用它们将导致发出警告。但是,--illegal-access
选项现在仍将保留(但计划在未来的版本中删除)。