Java“非法访问操作”方法将被弃用?

Java“非法访问操作”方法将被弃用?,java,java-11,java-reflection,Java,Java 11,Java Reflection,JDK 9+JVM发出非法访问操作警告后,如果您使用一些非法访问,如setAccessible() 我的问题 setAccessible()将来是否会被阻止 此功能的官方参考(如果不推荐)在哪里 我哪里都找不到参考资料,提前谢谢 WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by com.hazelcast.internal.networking.ni

JDK 9+JVM发出非法访问操作警告后,如果您使用一些非法访问,如
setAccessible()

我的问题

  • setAccessible()
    将来是否会被阻止
  • 此功能的官方参考(如果不推荐)在哪里
  • 我哪里都找不到参考资料,提前谢谢

    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
    
    1.
    setAccessible()
    将来是否会被阻止? 不,就我所知,没有人反对它,也没有人计划反对它

    您看到的警告与此方法有关,但不是直接的。Java 9中引入的Java平台模块系统在编译时和运行时(即反射)添加了更强的封装。运行时规则由
    #setAccessible(boolean)
    记录:

    C
    中的调用者可以使用此方法来启用对声明类
    D
    的成员的访问,前提是以下任何一项保持不变:

    • C
      D
      在同一模块中
    • 成员是公共的,
      D
      在包含
      D
      的模块导出到至少包含
      C
      的模块的包中是公共的
    • 成员受静态保护,
      D
      在包含
      D
      的模块导出到至少包含
      C
      的模块的包中是公共的,
      C
      D
      的子类
    • D
      位于包含
      D
      的模块至少打开到包含
      C
      的模块的包中。未命名模块和打开模块中的所有包都对所有模块开放,因此当
      D
      位于未命名模块或打开模块中时,此方法始终成功
    当声明类位于调用方的不同模块中,且包含声明类的包未对调用方的模块打开时,此方法不能用于启用对私有成员、具有默认(包)访问权限的成员、受保护的实例成员或受保护的构造函数的访问

    当反射可以自由地访问任何它想要的东西时,这是一个从Java8开始的突破性的改变(假设没有
    SecurityManager
    )。突破性的更改是一个问题,因为Java以向后兼容性为荣。为了给库和框架提供足够的时间进行迁移,他们针对特定场景放松了这种强大的封装(见下文)


    2.此功能的官方参考(将来将被弃用)在哪里? 您看到的警告与
    --非法访问
    选项有关,该选项由以下文件记录:

    当在运行时出现时,
    --非法访问=
    采用关键字参数来指定操作模式:

    注意:此选项将在将来的版本中删除

    • permit
      此模式打开运行时映像中每个模块中的每个包,以便在所有未命名模块(例如类路径上的代码)中编码(如果该包存在于JDK 8中)[强调添加]。这可以通过平台的各种反射API实现静态访问(例如,通过编译字节码和深度反射访问)。对任何此类包的第一次反射访问操作将导致发出警告。但是,首次发生后不会发出警告。此单一警告描述了如何启用更多警告此模式是当前JDK的默认模式,但在将来的版本中将更改[强调添加]

    • 警告
      :此模式与“允许”模式相同,只是针对每个非法反射访问操作发出警告消息

    • debug
      :此模式与warn模式相同,只是针对每个非法反射访问操作都会发出警告消息和堆栈跟踪

    • deny
      :此模式禁用所有非法访问操作,但由其他命令行选项启用的操作除外,例如
      --add opens
      此模式将成为未来版本的默认模式[强调添加]

    默认模式,
    --非法访问=许可
    ,旨在让您了解类路径上至少一次反射性访问任何JDK内部API的代码。要了解所有此类访问,可以使用警告或调试模式。对于类路径上需要非法访问的每个库或框架,您有两个选项:

    • 如果组件的维护者已经发布了一个不再使用JDK内部API的固定版本,那么您可以考虑升级到那个版本。

    • 如果组件仍然需要修复,那么您可以联系它的维护人员,让他们使用正确的导出API替换JDK内部API

    如果必须继续使用需要非法访问的组件,则可以通过使用一个或多个
    --add opens
    选项仅打开需要访问的内部软件包来消除警告消息

    要验证您的应用程序是否已为JDK的未来版本做好准备,请使用
    --非法访问=拒绝
    以及任何必要的
    --添加打开
    选项运行它。任何剩余的非法访问错误都很可能是由于编译代码对JDK内部API的静态引用造成的。您可以通过运行带有
    --jdk internals
    选项的
    jdeps
    工具来识别它们。出于性能原因,当前的JDK不会对非法的静态访问操作发出警告

    总结强调的部分:

  • 默认模式为
    permit
    • 这允许未命名模块(即类路径)中的代码访问运行时映像(即JDK)中模块内的成员,即使这些成员位于未导出/未打开的包中(只要这些包