博客
关于我
Java的非法反射警告illegal reflective access operation
阅读量:444 次
发布时间:2019-03-06

本文共 2222 字,大约阅读时间需要 7 分钟。

在JDK9中,反射机制对非公开成员的访问实施了更严格的限制。这一变化让许多依赖反射机制的代码出现了警告信息。以下内容将详细解释这一变化及其对开发者的影响。

反射机制在Java开发中广泛应用,尤其是在处理需要动态访问非公开成员(如私有字段或方法)的场景中。但在JDK9中,这种机制被加上了更多的安全保护措施。反射操作如果尝试访问非公开的字段或方法,将首次显示一个警告信息。为了更好地理解这些变化,我们可以通过以下方式来解决问题:

首先,了解反射访问限制的背景

在JDK8及之前的版本中,反射允许开发者访问类的非公开成员(如私有字段或方法),这通过反射机制实现。这种做法虽然在某些情况下非常有用,但并不推荐,因为它违反了代码的封装原则。JDK9则对反射的访问权限进行了更严格的控制,使得非公开成员的访问变得更加受限。

其次,具体示例分析

考虑以下代码片段:

import java.lang.reflect.Field;import java.util.ArrayList;public class TestReflect {    public static int getCapacity(ArrayList
l) throws Exception { Field dataField = l.getClass().getDeclaredField("elementData"); dataField.setAccessible(true); return ((Object[]) dataField.get(l)).length; } public static void main(String[] args) { var arr = new ArrayList<>(4); try { System.out.println("capacity:" + TestReflect.getCapacity(arr)); } catch (Exception e) { e.printStackTrace(); } }}

在JDK8中,这段代码能够正常运行并输出容量信息。然而,在JDK9中,执行时会显示以下警告信息:

WARNING: Illegal reflective access by TestReflect (file:/tmp/TestReflect.java) to field java.util.ArrayList.elementData

此外,还会显示以下提示信息:

WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operationsWARNING: All illegal access operations will be denied in a future release

然后,解决方案与最佳实践

面对JDK9反射限制,开发者有多种解决方案。首先,了解反射限制的具体表现:

  • 非公开成员的访问控制:JDK9反射机制现在会遵循Java模块化的访问控制规则。即使通过反射设置字段为可访问,也需要确保所访问的字段所在的类模块允许被访问。

  • 使用公开API:对于需要访问非公开成员的场景,尽量使用类提供的公开API。例如,ArrayList 提供了 size() 和 isEmpty() 等方法来获取容量信息,这些方法应该被优先使用。

  • 代码优化与重构:如果必须访问私有字段或方法,可以考虑以下措施:

    • 模块化设计:通过合理设计模块,避免对其他模块的私有成员进行直接访问。
    • 暴露必要的API:在需要反射访问的类中,添加适当的公开方法或字段,避免强行通过反射访问。
    • 代码审查与测试:定期审查代码,确保所有反射访问操作都符合当前的访问控制规则。
  • 最后,应对反射限制的策略

    为了应对JDK9反射限制,可以采取以下策略:

  • 后退到JDK8:如果代码对JDK9的反射限制无法适配,可以考虑将JDK版本锁定在8.x系列。这样可以避免反射访问警告的问题。

  • 使用特定选项:在JVM启动时添加特定的选项来控制反射访问的警告级别。例如:

    • --illegal-access=warn:仅显示警告信息。
    • --illegal-access=deny:严格拒绝非法反射访问,抛出 InaccessibleObjectException。
  • 模块化配置:在需要反射访问的类中,添加模块化配置以允许反射访问。例如,可以使用 --add-opens 选项:

    java --add-opens java.base/java.util=ALL-UNNAMED TestReflect.java

    这将使 ArrayList.elementData 字段在反射访问时可访问,而无需设置 setAccessible(true)。

  • 总结

    JDK9对反射机制的限制虽然增加了开发者的工作难度,但也促使我们重新审视代码设计。健康的代码应该避免过度依赖反射访问非公开成员。通过使用公开API、合理设计模块化以及定期代码审查,我们可以更好地应对这一变化,并确保代码的健壮性和可维护性。

    转载地址:http://orskz.baihongyu.com/

    你可能感兴趣的文章
    Python 常见的错误类型和继承关系
    查看>>
    python 常量_零基础学Python系列之一:Python的变量与常量
    查看>>
    Python 并发编程
    查看>>
    python 序列化操作
    查看>>
    Python 开发者,这 7 个 VS Code 插件极力推荐
    查看>>
    python手把手视频_硬货 | 手把手带你构建视频分类模型(附Python演练))
    查看>>
    python 录音左右声道_Python分离立体声wav压缩文件的左右声道
    查看>>
    Python 循环异或对文件进行加解密
    查看>>
    Python开发环境搭建(附VMware安装包及虚拟机环境)
    查看>>
    python 微信扫码登录_python实现微信第三方网站扫码登录(Django)
    查看>>
    Python 快速下载依赖
    查看>>
    python实现非参数统计的Cochran检验 (附完整源码)
    查看>>
    Python 手写数字识别-3-sklearn中的几种算法
    查看>>
    Python 打开文件注意事项
    查看>>
    python 批量修改文件名_python windows下批量修改文件名
    查看>>
    Python 抓取网页乱码问题 以及EXCEL乱码
    查看>>
    python 抓取网页内容
    查看>>
    python 按照当前日期创建文件
    查看>>
    Python 接口并发测试详解
    查看>>
    Python 接口自动化 —— requests框架
    查看>>