返回值_ASM检测方法返回值

本文介绍如何利用ASM这个字节码修改工具,来校验游戏接口的返回值是否符合预期。通过分析字节码指令,确定了引用返回值会使用areturn指令,并在其前存在aload指令。通过查找aload指令对应的局部变量索引,可以实现返回值的检测。文中给出了关键代码实现,并提示若要获取实际返回类型,可找到与局部变量索引相同的astore指令。
摘要由CSDN通过智能技术生成

    众所周知ASM是一个修改字节码的利器,此为前文.

   我们游戏中有一个很重要的接口大致如下所示(因为历史原因返回值无法修改)

public Object load() {    BaseClass baseClass = new ImplClass();    return baseClass;}

方法的返回值是一个Object,但是期望返回的是基于某个基类的值.如果返回值写错了会在跨服序列化的时候失败,导致游戏的跨服玩法出现重大问题(内网出现过此问题).本着把Bug扼杀在摇篮中的思想的.就想着能不能写一段代码来校验这个函数呢?所以才用到了我们今天的主角ASM.

    话不多说我们直接入正题,要怎么检测我们先看下上面代码的反编译字节码(此处可能需要一丢丢字节码的知识)

 0: new           #2                  // class com/jiang/asm/checkMethodReturn/ImplClass 3: dup 4: invokespecial #3                  // Method com/jiang/asm/checkMethodReturn/ImplClass."":()V 7: astore_1 8: aload_1 9: areturn

上面是生成的字节码指令,由上面的代码我们可知,返回一个引用对象使用的是areturn指令,此指令没有栈操作数.那么可得出,在areturn指令之前必然会有一条aload指令把本地变量推到栈上.因此我们就可以推导出几个信息:

    1 引用返回使用的是areturn指令 

    2 areturn指令之前必然有一条aload指令

    3 aload 指令是会会操作局部变量的

由此得出结论,我们只要找到我们关键的那条aload指令操作的局部变量索引,通过该索引找到局部变量的定义,我们就能对此作出检测.

    通过翻阅Asm的tree api,在MethodNode中查询到了以下信息

37f85858d23ec03498acf61d715f1cc0.png

instructions保存的是一个方法里面用到的所有指令,localVariables保存的是所有用到的局部变量(这里涉及到一个局部变量复用的问题,不过该问题不在今天的讨论范畴内).下面就是关键代码.

9ef6ab8c15d43bf73be1d0ab43b4e489.png

这个功能到此就结束了.

    (ASM似乎把aload_0 aload_1 这种指令全部替换成 aload index 这种指令,这里的代码暂时没有深入研究)

    贴心小提示(如果想要知道返回的实际类型,那么只需要找到最后一次和此局部变量下标相同的astore 指令即可 astore指令是把栈上的值赋给本地变量)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值