博客
关于我
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 从入门到精通:30天速成教程到底有多狠?你能坚持下来吗?
    查看>>
    Python 从数据库中存储和检索密码的最安全方法
    查看>>
    Python语言及其应用 - 知识点遍历
    查看>>
    Python 优化提速的 8 个小技巧
    查看>>
    Python 余弦相似度与皮尔逊相关系数 计算
    查看>>
    python 使用execjs 报编码错误解决办法,UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xac in position 145: il
    查看>>
    python 使用filetype校验文件
    查看>>
    Python 使用flush函数将缓冲区数据立即写磁盘
    查看>>
    python 使用in判断不准确,in不好使
    查看>>
    Python 使用pandas 进行查询和统计详解
    查看>>
    Redis 配置文件redis.conf详细解释
    查看>>
    python网络爬虫(2)——scrapy框架的基础使用
    查看>>
    python网络爬虫实例教程试读_Python网络爬虫实战教程(全套完整版) - 学途无忧网 - 做技术的王者 - Powered By EduSoho...
    查看>>
    Python 使用哈希函数用于加密
    查看>>
    Python 依赖管理的革新——Poetry 深度解析
    查看>>