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

    你可能感兴趣的文章
    Oracle-定时任务-JOB
    查看>>
    oracle.dataaccess 连接池,asp.net使用Oracle.DataAccess.dll连接Oracle
    查看>>
    oracle00205报错,Oracle控制文件损坏报错场景
    查看>>
    Oracle10g EM乱码之快速解决
    查看>>
    Oracle10g下载地址--多平台下的32位和64位
    查看>>
    Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
    查看>>
    oracle11g dataguard物理备库搭建(关闭主库cp数据文件到备库)
    查看>>
    Oracle11G基本操作
    查看>>
    Oracle11g服务详细介绍及哪些服务是必须开启的?
    查看>>
    Oracle11g静默安装dbca,netca报错处理--直接跟换操作系统
    查看>>
    oracle12安装软件后安装数据库,然后需要自己配置监听
    查看>>
    Oracle——08PL/SQL简介,基本程序结构和语句
    查看>>
    Oracle——distinct的用法
    查看>>
    Oracle、MySQL、SQL Server架构大对比
    查看>>
    oracle下的OVER(PARTITION BY)函数介绍
    查看>>
    Oracle中DATE数据相减问题
    查看>>
    Oracle中merge into的使用
    查看>>
    oracle中sql查询上月、本月、上周、本周、昨天、今天的数据!
    查看>>
    oracle中sql的case语句运用--根据不同条件去排序!
    查看>>
    Oracle中Transate函数的使用
    查看>>