什么是非法反射访问?

简介: 反射通常由需要检查或修改在 Java 虚拟机中运行的应用程序的运行时行为的能力的程序使用。这是一个相对高级的功能,只能由对语言基础知识有很强掌握的开发人员使用。考虑到这一点,反射是一种强大的技术,可以使应用程序执行原本不可能完成的操作。

一、反射的用途

反射通常由需要检查或修改在 Java 虚拟机中运行的应用程序的运行时行为的能力的程序使用。这是一个相对高级的功能,只能由对语言基础知识有很强掌握的开发人员使用。考虑到这一点,反射是一种强大的技术,可以使应用程序执行原本不可能完成的操作。

二、反射的缺点

反射很强大,但不应该乱用。如果可以在不使用反射的情况下执行操作,那么最好避免使用它。通过反射访问代码时应牢记以下问题。

  • 性能开销
    由于反射涉及动态解析的类型,因此无法执行某些 Java 虚拟机优化。因此,反射操作的性能比非反射操作慢,因此应避免在性能敏感的应用程序中频繁调用的代码段中使用反射操作。
  • 安全限制
    反射需要运行时权限,在安全管理器下运行时可能不存在该权限。对于必须在受限安全上下文(例如 Applet)中运行的代码来说,这是一个重要的考虑因素。
  • 内部结构暴露
    由于反射允许代码执行在非反射代码中非法的操作(例如访问private字段和方法),因此使用反射可能会导致意外的副作用,这可能会导致代码功能失调并可能破坏可移植性。反射代码破坏了抽象,因此可能会随着平台的升级而改变行为。

    三、什么是非法的反射访问

    默认情况下,对包具有运行时反射访问权限的模块可以看到包的public类型(及其嵌套public和protected类型)。但是,其他模块中的代码可以访问公开包中的所有类型以及这些类型中的所有成员,包括privatevia 成员 setAccessible。即,访问public类型(及其嵌套public和protected类型)被认为是合法的,访问privatevia 成员被认为是非法。

    四、什么定义了非法反射访问?

    从JDK9开始默认情况下放宽了某些 JDK 包的强封装,种放松是在运行时由新的启动器选项 --illegal-access控制的,
  • --illegal-access=permit 打开运行时映像中每个模块中的每个包,以在所有未命名模块中进行编码,即,如果该包存在于 JDK 8 中,则在类路径上进行编码。这可以实现静态访问​​(即通过编译的字节码)和深度访问通过平台的各种反射 API 进行反射访问。
    对任何此类包的第一次反射访问操作都会导致发出警告,但此后不会发出警告。此单个警告描述了如何启用进一步的警告。该警告无法被抑制。此模式是 JDK 9 中的默认模式。它将在未来版本中逐步淘汰并最终删除。

  • --illegal-access=warn 与permit 相同,只是为每个非法反射访问操作发出警告消息。

  • --illegal-access=debug 与warn相同,只是针对每个非法反射访问操作都会发出警告消息和堆栈跟踪。

  • --illegal-access=deny 禁用所有非法访问操作,但由其他命令行选项启用的操作除外,例如--add-opens.此模式将成为未来版本中的默认模式。

    五、如何解决?

    可以使用“--add-opens”

--add-opens <source-module>/<package>=<target-module>(,<target-module>)*

假设有一个错误它来自 模块 java.base,包 java.lang:

java.lang.ClassLoader.findLoadedClass(java.lang.String)

按照上面的样式带入:

java --add-opens=java.base/java.lang=ALL-UNNAMED -jar example.jar
目录
相关文章
|
22天前
|
缓存 安全 网络安全
静态代理IP访问失败的问题解释?
本文介绍了在浏览器中使用静态代理IP访问失败的多种可能原因,包括代理设置错误、代理服务器问题、站点策略限制、网络连接问题、浏览器设置问题、代理类型不支持及认证问题等,并提供了相应的解决建议。
27 1
|
4月前
|
传感器 监控 安全
预防非法访问
【8月更文挑战第19天】
106 7
|
7月前
如何处理代理的404错误
如何处理代理的404错误
353 8
|
7月前
|
C++
C++ 访问说明符详解:封装数据,控制访问,提升安全性
C++ 中的访问说明符(public, private, protected)用于控制类成员的可访问性,实现封装,增强数据安全性。public 成员在任何地方都可访问,private 只能在类内部访问,protected 则允许在类及其派生类中访问。封装提供数据安全性、代码维护性和可重用性,通过 setter/getter 方法控制对私有数据的访问。关注公众号 `Let us Coding` 获取更多内容。
96 1
|
7月前
如何判断代理ip的匿名程度
如何判断代理ip的匿名程度
|
测试技术
静态方法抛出运行时异常导致反射生成实例失败
静态方法抛出运行时异常导致反射生成实例失败
78 0
|
安全
非法文件的包含攻击是什么意思?底层原理是什么?
非法文件的包含攻击是什么意思?底层原理是什么?
315 0
|
前端开发
如何使用反射进行参数效验
各位可能会有疑问,为什么不使用 `@Valid `注解呢!各位兄弟我也想用啊!但是没办法啊!项目性质导致的。项目会对接各种渠道方,但是所有渠道方都是用同一个实体进行传递的(通用性),但是呢,每个渠道方对字段必传的效验又不一样(用户是上帝)
869 0