Java中的”illegal access operations”方法会被弃用吗?

huangapple go评论80阅读模式
英文:

Java `illegal access operations` method will be deprecated?

问题

After JDK 9+ JVM emit illegal access operations warning if you use some illegal access like setAccessible().

我的问题

  1. setAccessible() 是否会在将来被阻止?
  2. 如果会被弃用,官方参考在哪里?

我无法在任何地方找到参考资料,提前感谢。

WARNING: Illegal reflective access by com.hazelcast.internal.networking.nio.SelectorOptimizer (file:/var/folders/9w/wp9vfqmn2ql0mp3lgym0bxf40000gn/T/toy.war-spring-boot-libs-0024b388-730f-430b-b21b-1611bd2ad612/hazelcast-4.0.2.jar) to field sun.nio.ch.SelectorImpl.selectedKeys
WARNING: Please consider reporting this to the maintainers of com.hazelcast.internal.networking.nio.SelectorOptimizer
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release```

<details>
<summary>英文:</summary>

After JDK 9+ JVM emit illegal access operations warning if you use some illegal access like `setAccessible()`.

My questions

1. Is `setAccessible()` will be blocked in the future?
2. Where is official reference(if it will be deprecated) for this feature?

I can&#39;t find reference anywhere, thanks in advance.


WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.hazelcast.internal.networking.nio.SelectorOptimizer (file:/var/folders/9w/wp9vfqmn2ql0mp3lgym0bxf40000gn/T/toy.war-spring-boot-libs-0024b388-730f-430b-b21b-1611bd2ad612/hazelcast-4.0.2.jar) to field sun.nio.ch.SelectorImpl.selectedKeys
WARNING: Please consider reporting this to the maintainers of com.hazelcast.internal.networking.nio.SelectorOptimizer
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release


</details>
# 答案1
**得分**: 9
# 1. `setAccessible()`方法将来会被阻止吗?
不会,[`AccessibleObject#setAccessible(boolean)`][1] 没有被弃用,据我所知,也没有计划弃用它。
你看到的警告与这个方法相关,但不是直接相关的。Java 9引入的_Java平台模块系统_在编译时和运行时(即反射)都加强了封装。运行时规则由`#setAccessible(boolean)`文档化:
&gt; 如果以下情况之一成立,调用类`C`的调用者可以使用这个方法来启用对声明类`D`的成员的访问权限:
&gt;
&gt; * `C`和`D`在同一个模块中。
&gt; * 成员是public,而`D`是在将其导出到至少包含`C`的模块的包中的public。
&gt; * 成员是protected static,`D`在将其导出到至少包含`C`的模块的包中的public,而`C`是`D`的子类。
&gt; * `D`在将其导出到至少包含`C`的模块的包中。无名模块和开放模块中的所有包都对所有模块都开放,因此当`D`在无名模块或开放模块中时,此方法总是成功的。
&gt; 当声明类与调用者所在的模块不同且包含声明类的包未对调用者的模块开放时,不能使用此方法启用对私有成员、默认(包)访问权限、受保护的实例成员或受保护的构造函数的访问权限。
这是与Java 8不同的破坏性变更,当时反射可以自由访问任何它想要的内容(假设没有`SecurityManager`)。破坏性变更是一个问题,因为Java以向后兼容性为傲。为了为库和框架提供足够的时间进行迁移,他们为特定情况放宽了这种强封装(见下文)。
---
# 2. 未来会被弃用的官方参考文档在哪里?
你看到的警告与`--illegal-access`选项相关,该选项在[`java`工具规范][2]中有文档记录:
&gt; 当在运行时存在时,`--illegal-access=`采用关键字_参数_来指定操作模式:
&gt;
&gt;&gt; **注意:此选项将在将来的版本中删除。**
&gt;
&gt; * `permit`:**这种模式会打开运行时映像中所有未命名模块(例如类路径上的代码)中的每个模块中的每个包,如果该包存在于JDK 8中** _[重点添加]_。这允许通过平台的各种反射API进行静态访问(例如,通过编译的字节码和深度反射访问)。对任何此类包的第一次反射访问操作都会发出警告。然而,在第一次出现后不会发出警告。这个单一的警告描述了如何启用进一步的警告。**这种模式是当前JDK的默认模式,但将在将来的版本中更改** _[重点添加]_。
&gt;
&gt; * `warn`:此模式与`permit`相同,只是对每个非法的反射访问操作发出警告消息。
&gt;
&gt; * `debug`:此模式与`warn`相同,只是对每个非法的反射访问操作发出警告消息和堆栈跟踪。
&gt;
&gt; * `deny`:此模式禁用除了其他命令行选项启用的非法访问操作之外的所有非法访问操作,例如`--add-opens`。**这种模式将成为将来版本的默认模式** _[重点添加]_。
&gt;
&gt; 默认模式`--illegal-access=permit`旨在让您意识到类路径上的代码反射访问任何JDK内部API,至少有一次。要了解所有这种访问,您可以使用警告或调试模式。对于类路径上需要非法访问的每个库或框架,您有两个选择:
&gt;
&gt; * 如果组件的维护者已经发布了不再使用JDK内部API的修复版本,那么您可以考虑升级到该版本。
&gt;
&gt; * 如果组件仍然需要修复,那么您可以联系其维护者,并要求他们使用适当的导出API替换他们对JDK内部API的使用。
&gt;
&gt; 如果您必须继续使用需要非法访问的组件,那么您可以使用一个或多个`--add-opens`选项,仅将所需访问权限打开到那些内部包。要验证您的应用程序是否已准备好迎接JDK的未来版本,请使用`--illegal-access=deny`运行它,以及任何必要的`--add-opens`选项。任何剩余的非法访问错误很可能是由于编译代码对JDK内部API的静态引用而导致的。您可以通过使用`jdeps`工具以`--jdk-internals`选项运行它来识别这些问题。出于性能原因,当前的JDK不会为非法的静态访问操作发出警告。
总结一下重点:
1. 默认模式是`permit`。
* 这允许未命名模块(即类路径)中的代码访问运行时映像中模
<details>
<summary>英文:</summary>
# 1. Is `setAccessible()` will be blocked in the future?
No, [`AccessibleObject#setAccessible(boolean)`][1] is not deprecated nor, as far as I&#39;m aware, are there plans to deprecate it. 
The warning you see is related to this method but not directly. The _Java Platform Module System_ introduced in Java 9 added stronger encapsulation, both at compile-time and run-time (i.e. reflection). The run-time rules are documented by `#setAccessible(boolean)`:
&gt; This method may be used by a caller in class `C` to enable access to a member of declaring class `D` if any of the following hold:
&gt;
&gt;* `C` and `D` are in the same module.
&gt;* The member is public and `D` is public in a package that the module containing `D` exports to at least the module containing `C`.
&gt;* The member is protected static, `D` is public in a package that the module containing `D` exports to at least the module containing `C`, and `C` is a subclass of `D`.
&gt;* `D` is in a package that the module containing `D` opens to at least the module containing `C`. All packages in unnamed and open modules are open to all modules and so this method always succeeds when `D` is in an unnamed or open module.
&gt;
&gt;This method cannot be used to enable access to private members, members with default (package) access, protected instance members, or protected constructors when the declaring class is in a different module to the caller and the package containing the declaring class is not open to the caller&#39;s module. 
This is a breaking change from Java 8 when reflection had free rein to access anything it wanted (assuming no `SecurityManager`). A breaking change is a problem since Java prides itself on backwards compatibility. In order to provide libraries and frameworks enough time to migrate they relaxed this strong encapsulation for a specific scenario (see below).
---
# 2. Where is official reference(that will be deprecated in the future) for this feature?
The warning you see is related to the `--illegal-access` option, which is documented by the [`java` tool specification][2]:
&gt; When present at run time, `--illegal-access=` takes a keyword _parameter_ to specify a mode of operation:
&gt;
&gt;&gt; **Note:** This option will be removed in a future release.
&gt;
&gt;* `permit`: **This mode opens each package in each module in the run-time image to code in all unnamed modules ( such as code on the class path), if that package existed in JDK 8** _[emphasis added]_. This enables both static access, (for example, by compiled bytecode, and deep reflective access) through the platform&#39;s various reflection APIs. The first reflective-access operation to any such package causes a warning to be issued. However, no warnings are issued after the first occurrence. This single warning describes how to enable further warnings. **This mode is the default for the current JDK but will change in a future release** _[emphasis added]_.
&gt;
&gt;* `warn`: This mode is identical to permit except that a warning message is issued for each illegal reflective-access operation.
&gt;
&gt;* `debug`: This mode is identical to warn except that both a warning message and a stack trace are issued for each illegal reflective-access operation.
&gt;
&gt;* `deny`: This mode disables all illegal-access operations except for those enabled by other command-line options, such as `--add-opens`. **This mode will become the default in a future release** _[emphasis added]_.
&gt;
&gt; The default mode, `--illegal-access=permit`, is intended to make you aware of code on the class path that reflectively accesses any JDK-internal APIs at least once. To learn about all such accesses, you can use the warn or the debug modes. For each library or framework on the class path that requires illegal access, you have two options:
&gt;
&gt; * If the component&#39;s maintainers have already released a fixed version that no longer uses JDK-internal APIs then you can consider upgrading to that version.
&gt;
&gt; * If the component still needs to be fixed, then you can contact its maintainers and ask them to replace their use of JDK-internal APIs with the proper exported APIs.
&gt;
&gt; If you must continue to use a component that requires illegal access, then you can eliminate the warning messages by using one or more `--add-opens` options to open only those internal packages to which access is required.
&gt;
&gt; To verify that your application is ready for a future version of the JDK, run it with `--illegal-access=deny` along with any necessary `--add-opens` options. Any remaining illegal-access errors will most likely be due to static references from compiled code to JDK-internal APIs. You can identify those by running the `jdeps` tool with the `--jdk-internals` option. For performance reasons, the current JDK does not issue warnings for illegal static-access operations.
To summarize the emphasized parts:
1. The default mode is `permit`.
* This allows code in the _unnamed module_ (i.e. class-path) to access members within modules in the run-time image (i.e. the JDK), even if those members are in non-exported/non-opened packages (so long as those packages existed in JDK 8).
2. Eventually the default mode will be `deny`.
* Any code that hasn&#39;t been properly migrated at this point will stop working. This is why you see the warning—they want you to fix the problem (either yourself, if your code, or by submitting a bug report, if third-party code).
3. The `--illegal-access` option itself will eventually be removed entirely.
In what release these changes will occur... I have no idea. However, the `--illegal-access` option will probably be removed one or two releases after the default mode becomes `deny`.
### Update (May 31, 2021)
[JEP 396: Strongly Encapsulate JDK Internals by Default][3] was delivered with Java 16 and makes the default mode `deny`. The `--illegal-access` option is still present.
[JEP 403: Strongly Encapsulate JDK Internals][4] is currently targeted for Java 17. This will make `permit`, `warn`, and `debug` modes ineffective and attempting to use them will result in a warning being emitted. However, the `--illegal-access` option will remain for now (but is planned to be removed in a future release).
[1]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean)
[2]: https://docs.oracle.com/en/java/javase/14/docs/specs/man/java.html#extra-options-for-java
[3]: https://openjdk.java.net/jeps/396
[4]: https://openjdk.java.net/jeps/403
</details>

huangapple
  • 本文由 发表于 2020年8月14日 14:00:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63407349.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定