博客
关于我
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/

    你可能感兴趣的文章
    Objective-C实现优先级调度算法(附完整源码)
    查看>>
    Objective-C实现优先队列算法(附完整源码)
    查看>>
    Objective-C实现伽玛Gamma函数(附完整源码)
    查看>>
    Objective-C实现位置型pid算法(附完整源码)
    查看>>
    Objective-C实现低通滤波器(附完整源码)
    查看>>
    Objective-C实现余弦cosx函数(附完整源码)
    查看>>
    Objective-C实现余数定理算法(附完整源码)
    查看>>
    Objective-C实现使用 2 个堆栈形成队列算法(附完整源码)
    查看>>
    Objective-C实现使用 radix-2 快速傅里叶变换的快速多项式乘法算法(附完整源码)
    查看>>
    Objective-C实现使用 ziggurat() 作为 OpenMP 并行程序中的随机数生成器 (RNG)(附完整源码)
    查看>>
    Objective-C实现使用DisjointSet 检测无向循环算法(附完整源码)
    查看>>
    Objective-C实现使用Prim算法确定图的最小生成树算法(附完整源码)
    查看>>
    Objective-C实现使用二元运算符将两个数字相加fullAdder算法(附完整源码)
    查看>>
    Objective-C实现使用分而治之找到单峰列表的峰值算法(附完整源码)
    查看>>
    Objective-C实现使用数组实现约瑟夫环(附完整源码)
    查看>>
    Objective-C实现使用矩阵求幂的第 n 个斐波那契算法(附完整源码)
    查看>>
    Objective-C实现使用管道重定向进程输入输出(附完整源码)
    查看>>
    Objective-C实现倒计时(附完整源码)
    查看>>
    Objective-C实现借记款项功能(附完整源码)
    查看>>
    Objective-C实现全年3天打渔,2天晒网(附完整源码)
    查看>>