asm中导出方法本地变量

在方法出现异常时需要把传入参数值和本地变量值异导出来供分析。之前因为测试的对象都是普通的值,写的loadLocalVarArray能正常工作。

这几天要在方法进入时inject一个long startTime供在方法退出时计算方法方法执行时间,发现如果本地变量是long和double本地变量栈中实际

占用两个位置,而nextLocal和firstLocal是本地变量栈的地址位置,根本无法知道实际的本地变量个数和具体的索引。

 

当然用for(int i=0;i< nextLocal-firstLocal;i++){

         try{   loadLocal(i+firstLocal) }catch(Exception ex){........}

}利用异常来判断是否有某个localIndex是可以牧举出来的,但是这样太猥琐了。

 

查看GeneratorAdapter发现有一个私有yojgList<Type> localTypes,在visit的时候,本地变量的type会被放在这个数组中。但是存放的方式几乎和栈中差不多。假如有三个double的亦是,栈中是:

 

firstLocal + 0

firstLocal + 2

firstLocal + 4

这样nextLocal-firstLocal是6,但是loadLocal(6)肯定出异常。而这个list也是把一个type set到对应的位置。这样它就需要把前面没有的地方填null.设置后是这样的:

 

0 J

1 null

2 J

3 null

4 J

这个list的长度是5,可以正确地 loadLocal(index).但是它是一个私有变量,我只好给GeneratorAdapter增加一个   

public int getLocalLength(){
        return this.localTypes.size();
}

 

说明:因为instrumention功能是独立天任何app的,它引用的库在premain中调用,那么如果应用中使用了同样的库而版本不同,则无法再载

入相同的类,因为premain在main之前已经载入了,为了防止版本冲突,我们是把其它 app常用库重新package进来的,这个工作是非常必要的,所以修改源码仍然可以接受。

 

有了这个getLocalLength()就好办了:

 

void loadVarArray() {

        Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
        int varCnt = getLocalLength();
        if (varCnt == 0) { //返回一个空数组
            push(0);
            newArray(OBJECT_TYPE);
            return;
        }

        /*
         * 先检查栈的空位(long和double占两个位,其一个标记为null),如果直接用栈长度指定数组
         * 则占位的位置为null,返回出去程序不知道是占位的null还是一个localVar的值为null
         */
        int arrLen = 0;
        for (int i = 0; i < varCnt; i++) {
            Type t = getLocalType(super.firstLocal + i);
            if (t != null)
                arrLen++;
        }
        push(arrLen); //实际需要的数组长度
        newArray(OBJECT_TYPE);
        int arrIndex = 0;
        for (int i = 0; i < varCnt; i++) {
            int index = super.firstLocal + i;
            Type t = getLocalType(index);
            if (t == null)
                continue;

            dup();
            push(arrIndex++);
            loadLocal(index, t);
            box(t);
            arrayStore(OBJECT_TYPE);
        }
    }

 

 

这样正确地把所有本地变量加载到数组中(数组现在在操作栈的栈顶,你可以访问它了)。

 

完整的实现:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
NiceBASIC文编程语言,是采用类似BASIC语法,并兼有C++的一些高级特性(比如:指针(Pointer)操作运算、自动化类(Class)、重载函数(OverLoad)、重载操作符(OverLoad)等等)集于一身的全文关键字的编程语言,简称NB。   其独特个性化的全文式编程模式,更易于国人理解和方便学习编程,不用懂英文也可以编写自己的程序软件。变量和函数等标识符名称,也可以用文表示,方便于源码的交流和省略注释说明。 基本功能:   NB内置有基本BASIC函数库,和图像库(用于编写游戏)。 功能扩展:   以静态库(LIB)链接形式调用标准C语言函数库里的函数。可以使用由标准C语言和汇编ASM编写的静态库(LIB)作为函数功能扩展。可以调用WIN32API的大部分函数,已经在内部定义(.bi文件相当于C语言的.h)声明,直接引用即可,就像C++的WINDOWS开发包(SDK)。 NB的编译器是采用开源编译器后续开发的,可以编译四种类型的可执行文件:   一、控制台程序。类似于DOS界面的命令行提示符,但只能运行在WIN32平台。   二、WINDOWS图形界面程序。调用系统的WIN32API来构建GUI窗体组件。   三、WIN32 DLL 动态链接库。导出函数可以为多种调用约定,比如:Stdcall(标准WINAPI)、 Cdecl(兼容C语言)、Pascal 。可供给其它语言调用。   四、静态链接库。供给标准的C语言调用链接。就是说NB的静态库是兼容C语言的LIB,互相通用。 为了方便编写代码,附带专业级的多功能高级编辑器:支持文的语法高亮,工程管理,代码提示补全,智能缩进,自动完成,插件,模板等功能。并且针对汉字输入字数多的缺点,采用首拼输入命令提示关联到函数名,变量名,常量名。比如要输入“如果”只须键入“rg”(“如果”二字的首拼)就会在提示列表出现“如果”,选择即可输出“如果”到编辑器,方便快捷。 虽然NB目前还没有可视化的集成开发环境(Visual IDE),但NB提供了构建完整标准WIN32应用程序的所有功能。作为小巧的编程工具和初级水平程序员进阶学习工具。选择NB应该是NB的选择!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值