Reflection.invokeMethod argument type mismatch

java.lang.IllegalArgumentException: argument type mismatch


异常背景

  1. 异常容灾
    1. 实现方案
      1. Spring AOP 捕获接口抛出的异常,保留当前类、接口、方法、入参信息
      2. 通过定时任务遍历当前需要重试的任务列表
      3. 通过反射机制重新调用接口方法
  2. 队列消息
    1. 上游应用先将数据存入DB,再发送MQ通知下游应用
    2. 但往往MQ的接收速度快于DB存入速度,导致下游发起查询功能时数据未录入到DB中
    3. 解决方案
      1. 时间延迟,下游应用接收到队列消息延迟5s再进行处理
      2. 查询重试,5s 内不断请求查询接口直到查询到数据
      3. 容灾重试,记录异常方法及入参,定时任务扫描重试,失败达到指定次数后邮件预警通知,手动处理
  3. 异常描述
    1. 消息内容:由于是通过消息队列传递信息,消息体为JSONObject(org.json.JSONObject)
    2. 存储接口:触发容灾后将接口入参转为JSON.toJSONString(底层实现为ObjectMapper) 字符串存入DB
    3. 反射调用:在重组参数及接口方法反射过程中程序运行正常;在Reflection.invokeMethod时出现参数不匹配异常
    4. 检查入参:此时检查调用方法是传入的params发现原本的org.json.JSONObject 被转为 map (LinkedHashMap) 形式
  4. 问题纠结
    1. 遇到问题时虽然检查了参数的内容,想到了与预期的JSONObject不符,但是当时在想可能就是默认的对应的映射关系
    2. 查询问题的重点放在了JSON工具的使用上,序列化与反序列化的工具使用,尝试换了ali的fastjson等其他工具类后发现问题依旧

异常排查

  1. 单元测试
    1. 写单元测试类只测试Reflection.invokeMethod方法,将org.json.JSONObject 转为 String ,再有 String 转回 JSONObjct 调用 Reflection.invokeMethod 方法
    2. 此时发生转换异常,原来的程序调用位置有多层try catch,未发现明显异常

Exception in thread “main” java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.json.JSONObject

  1. 问题定位
    1. org.json.JSONObject 在 toString()时转为 Map
    2. Map 无法逆向直接转为 org.json.JSONObject

异常解决

  1. 在调用Reflection.invokeMethod方法前获取参数时
  2. 判断如果是org.json.JSONObject.class 手动将参数Map转为JSONObject
  3. 问题解决

异常反思

  1. 认为最不可能出现问题的地方往往就是问题所在

    1. 发现生产环境服务访问偶尔出现丢包
      1. 检查各个机器节点响应,检查网络连接,查询日志
      2. 最终问题定位原因在于硬件故障
      3. 虽然一开始讨论时有人怀疑过硬件问题,但是因为这个原因发生的可能性太低了,所以一开始就被排除了
      4. 需要通过逐个机器停机测试的方式排查来最终定位
    2. 上述异常排查时只检查了Reflection.invoke方法参数入参,发现参数无误,没有仔细对照参数类型,或直接以为JSONObject与Map之间就是互逆转换,直接把排查问题的方向定位到JSON序列化的工具上,方向偏了,越走越远
  2. 适可而止,不要急于求成

    1. 不要一条道跑到黑,三十分钟没有结论,就说明要不方向错了,要不解决方案不正确,及时调整方向,避免过度纠结
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值