你说反射有点难追,我觉得应该知难而退。

news2024/10/9 22:15:45

文章目录

    • 问题
    • 源码解析
    • 溯源
    • 问题解决方案
      • 第一种:
      • 第二种:
      • 第三种:

问题

今天小伙伴遇到一个问题,有关于反射的,写个demo,大家看一下。

在这里插入图片描述

如上,运行之后会报错:出现了非法参数。

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.ossa.web3.reflect.A.age to (int)10
	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:191)
	at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.setInt(UnsafeObjectFieldAccessorImpl.java:114)
	at java.base/java.lang.reflect.Field.setInt(Field.java:984)
	at com.ossa.web3.reflect.TestReflect.main(TestReflect.java:15)

源码解析

就此问题,我们来解析一下源码。

步入setInt()方法,注意这三个红色框框:一个是上面我们抛出的错误,这里主要是解包失败,类型没匹配成功。

getFieldAccessor(obj)方法获取一个属性访问器FieldAccessor。

我们来看一看是如何获取FieldAccessor的。

步入getFieldAccessor(obj)方法,在步入acquireFieldAccessor(ov)方法

在这里插入图片描述

这里会由反射工厂创建一个UnsafeObjectFieldAccessorImpl属性访问器tmp,然后将这个访问器添加进root中

这个UnsafeObjectFieldAccessorImpl可就有意思了。

它里面会有一下setXx、getXx方法,除了set()方法之外,其余都是抛出非法参数异常。

行吧,都到这了,我们顺便看看反射工厂是如何创建属性访问器的:

tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck);

步入newFieldAccessor方法中,最终调用UnsafeFieldAccessorFactory.newFieldAccessor(field, isReadOnly);

在这里插入图片描述
步入核心方法newFieldAccessor中:

我们来好好看看这个方法,这个方法中是反射修改属性的核心方法,包括修改静态属性、final属性、volatile属性等。

在这里插入图片描述

整体来说,就是优先判断属性是不是静态的,再判断其是否是final和volatile。当然我们这里不是静态,也不是final和volatile。

来看看吧:

我们这里属性是type = class Java.lang.Integer

这里面都是各种类型判断。

在这里插入图片描述

溯源

那我们继续走,看看会发生什么。

哦?到这里,貌似是可以匹配上。

但是实际并没有。

Integer.TYPE = int

而我们的type是class Java.lang.Integer

一个是基本数据类型,一个是引用类型,噶了。

在这里插入图片描述
所以最后都没匹配成功,创建了一个UnsafeObjectFieldAccessorImpl。然而这个访问器最后调用setInt()方法会抛出非法参数异常,那么问题根源就找到了。

在这里插入图片描述

问题解决方案

所以,我们该怎么解决这个问题呢?

第一种:

我们可以将属性的类型改为int,就像这样:

在这里插入图片描述
然后看一下核心源码的判断部分:这里就匹配上了,创建了UnsafeIntegerFieldAccessorImpl对象。

在这里插入图片描述
最后调用UnsafeIntegerFieldAccessorImpl对象的setInt方法。

然后调用本地方法 @IntrinsicCandidate public native void putInt(Object o, long offset, int x);

在这里插入图片描述

第二种:

解决方法(无效);

你说有没有可能将属性的类型由Integer变成int,这样不就可以用setInt方法,最后也可以匹配成功么?

我们来试试,

jdk8:类型是可以转换成功,但是值设置不进去,具体原因不详,谁知道记得评论告诉我。
在这里插入图片描述

jdk17:就更有意思了,压根连type属性就反射不到。

在这里插入图片描述

第三种:

解决方法:

使用set方法,这样在核心源码匹配的时候就都匹配不上,直接创建UnsafeObjectFieldAccessorImpl对象,调用set方法:

这个靠谱,没有对应类型的就都可以用这个去调用本地native方法。


完结了,撒花,又浪费10分钟写文章,你们谁要是看到这里,就帮忙看看上面为什么修改属性类型之后不能设置值?

爱你们,么么。♥♥♥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/190896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习论文: YOLOv6 v3.0: A Full-Scale Reloading及其PyTorch实现

深度学习论文: YOLOv6 v3.0: A Full-Scale Reloading及其PyTorch实现 YOLOv6 v3.0: A Full-Scale Reloading PDF: https://arxiv.org/pdf/2301.05586.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/shanglianlm0525/PyTorch…

2023年IB考试该如何备考?

IB课程考试时间 考试时间:IBO官方近期公布了2023年的考试时间与计划,中国学生IB考试时间定在2023.5.1至5.19。 在世界各地,学生在IB体系中均按照相同的教学大纲进行,并且于毕业时参加全球统一考试。一年两次(北半球于5…

拉伯证券|北向资金1月净买入超1400亿,啥信号?

2023年1月份,电视剧《狂飙》热播,被视为A股投资“风向标”的北向资金也敞开“狂飙”态势,月内五次净买入额超百亿,1月30日单日净买入额更是创2021年12月以来新高。 单月净买入超1400亿,刷新纪录! 北向资金…

Ventoy安装教程

目录Ventoy五大优势Ventoy安装教程其他链接Ventoy是一款国人开发的新一代多ISO启动引导程序,用户只需要将所需的ISO镜像文件拷贝至优盘中即可在Ventoy界面中选择自己想要的ISO镜像文件。 Ventoy五大优势 广泛兼容:支持包括Windows 10、Windows 8.1、Wind…

【哈希表】leetcode15. 三数之和(C/C++/Java/Python/Js)--梦破碎的地方

leetcode15. 三数之和--梦破碎的地方1 题目2 思路2.1 哈希解法--含代码2.2 双指针2.3 去重逻辑的思考2.3.1 a的去重2.3.2 b与c的去重3 代码--双指针法3.1 C版本3.2 C版本3.3 Java版本3.4 Python3版本3.5 JavaScript版本4 总结用哈希表解决了两数之和 ,那么三数之和呢…

[Lua实战]Skynet-2.如何启动(Win10-WSL环境Ubuntu18.04)[开箱可用]

Skynet-2.如何启动Win10-WSL环境Ubuntu18.04接上文,在linux运行skynet1.WIN10-WSL1.1 用Microsoft Store安装WSL(会遇到商店下载失败等问题...)1.1.1控制面板支持Linux配置1.1.2Microsoft Store 找到 Ubuntu18.041.1.3如果遇到安装问题如图请直接跳到1.21.2 使用PowerShell工具…

概论_第7章_参数估计_点估计之极大似然估计__性质

一 性质 极大似然估计 有一个简单有用的性质: 如果 θ^\hat\thetaθ^ 是 θ\thetaθ的极大似然估计, 则对任一 θ\thetaθ的函数g(θ)g(\theta)g(θ), 其极大似然估计为 g(θ^)g(\hat\theta)g(θ^) . 该性质称为极大似然估计的不变性,它使…

项目代码版本控制与维护

一、版本命名规则 1.1 需求开发分支命名规则 格式:dev_v版本号_需求名称 案例:dev_v01.31_TX202301141 dev_v01.31_数字产品平台订单查询优化 1.2 测试环境发布分支命名规则 格式:uat_deploy 1.3 预上环境分支命名规则 格式&#xff1a…

操作系统权限提升(六)之系统错误配置-不安全的服务提权

系列文章 操作系统权限提升(一)之操作系统权限介绍 操作系统权限提升(二)之常见提权的环境介绍 操作系统权限提升(三)之Windows系统内核溢出漏洞提权 操作系统权限提升(四)之系统错误配置-Tusted Service Paths提权 操作系统权限提升(五)之系统错误配置-PATH环境变量提权 注&…

九种查找算法-B树/B+树

B树/B树 在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二…

数学建模与数据分析 || 2. 结构化与非结构化数据的读取方法

结构化与非结构化数据的读取方法 文章目录结构化与非结构化数据的读取方法1. 结构化数据的读取1.1 pandas 读取 excel 文件1.2 pandas 读取 csv 文件1.3 pandas 读取 txt 文件1.4 利用 scipy 读取 mat 格式文件数据1.5 利用 numpy 存储和读取 npz 格式文件2. python 读取图像的…

SpringBoot国际化

软件的国际化软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。国际化internationalization,在i和n之间有 18 个字母&…

AXI 总线协议学习笔记(2)

引言 从本文开始,正式系统性学学习AXI总线。 如何获取官方协议标准? 第一步:登陆官网:armDeveloper 第二步:登录,无账号需要注册 第三步:点击文档 第四步: 第五步:浏…

最新最全阿里内推830道面试题合集,BATJ都有问到

小小叹语:你是否对你现在的生活状态有满足感呢?逝去日子经过多少风雨波折才有今天的成就,只有努力向上不断闯断,热爱竟逐每秒每分钟,才能拥有的更多。 而对于一个程序员来说,如果说你是想要在互联网行业找…

【题解】2023牛客寒假算法基础集训营4

目录A 清楚姐姐学信息论思路B. 清楚姐姐学构造思路C. 清楚姐姐学01背包(Easy Version)思路D. 清楚姐姐学01背包(Hard Version)思路E. 清楚姐姐打怪升级思路F. 清楚姐姐学树状数组思路G. 清楚姐姐逛街(Easy Version)思路L. 清楚姐姐的三角形I思路M. 清楚姐姐的三角形II思路A 清楚…

Grafana 系列文章(四):Grafana Explore

👉️URL: https://grafana.com/docs/grafana/latest/explore/ 📝Description: Explore Grafana 的仪表盘 UI 是关于构建可视化的仪表盘。Explore 剥离了仪表盘和面板选项,这样你就可以。.. Grafana 的仪表盘 UI 是关于构建可视化的仪表盘的。…

happen-before

happen-before 什么是happen-before JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happens-before关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证a操作将对b操作可见). …

Leetcode(上)

Leetcode(上) 1.LeetCode01 两数之和 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一…

数据结构——优先级队列和堆

目录 一、堆 1.概念 2.堆的存储方式 3.性质 4.模拟实现堆(以小根堆为例) (1).堆的调整 (2).堆的创建 (3).建堆的时间复杂度 (4).堆的插入和删除 5.堆…