ASM函数监听实现(三)拦截注入函数的参数值 (函数执行前)

本文详细阐述了如何使用ASM技术实现对参数传入值的拦截,包括特定值判断与方法调用,通过实例展示了ASM AOP的运用,并提供测试代码以验证拦截效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇ASM中打印出了被注入函数参数的传入值,[url]http://xkorey.iteye.com/admin/blogs/1667944[/url]

现在将要实现对参数传入值的拦截,不符合判断规则的传入值,将会被直接返回。
实现如下效果:

// 打印出参数传入值
start value:error
// 发现值等于 error 时直接返回
error,program will exit.
//属性值并未被更改
default
// 打印出传入值
start value:change
end value:change
// 属性值被更改
change


被拦截的方法是helloWorld中的sayHello

public class helloWorld {

public String va="default";

public void sayHello(String param){
va=param;
}
}


测试代码


asmAopGenerator aag = new asmAopGenerator();
helloWorld hw = (helloWorld) aag.proxy(helloWorld.class, "sayHello", "it's begin", "it's end");
// 传入值是error时直接返回 va的值没改变
hw.sayHello("error");
// 打印出default
System.out.println(hw.va);
// va的值被改变
hw.sayHello("change");
// 打印出 va的值为 change
System.out.println(hw.va);


注入到被拦截类的对象:


public class asmAopInvoker {

public static int methodEnd(String evtID){
System.out.println("end value:"+evtID);
return 0;
}

public static int methodStart(String evtID){
System.out.println("start value:"+evtID);
if(evtID.equals("error")){
System.out.println("error,program will exit.");
return 1;
}
return 0;
}

}


方法拦截对象就是上一篇中的asmAopMethodAdapter
具体修改为

public class asmAopMethodAdapter extends MethodAdapter implements Opcodes{

private final static int EXCEPTION_STACK = 2 + 1;//max_stack至少需要能够容纳2个常量地址(监控方法使用)和1个exception地址

private Label try_catch_start,try_catch_end;

private String startInfo,endInfo;

public asmAopMethodAdapter(MethodVisitor mv,String start,String end) {
super(mv);
try_catch_start = new Label();
try_catch_end = new Label();
startInfo = start;
endInfo = end;
}

public void visitCode() {
mv.visitCode();
mv.visitLabel(try_catch_start);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
// 加入if标签
Label if_Lable = new Label();
// 获得函数 methodStart 的返回值
mv.visitVarInsn(ALOAD, 1);
// 调用 methodStart函数
// (Ljava/lang/String;)I 意为:接受一个类型为string参数
// 返回值为int的函数
mv.visitMethodInsn(INVOKESTATIC, "asmAop/asmAopInvoker",
"methodStart", "(Ljava/lang/String;)I");
// 访问if 标签
// 疑惑 asm4-guide 中说明 IFEQ的意思是:jump if i == 0。但我在asm 3.3.1中貌似IFEQ是 jump if i==1
mv.visitJumpInsn(IFEQ, if_Lable);
// 写入 return
mv.visitInsn(RETURN);
// 结束if标签
mv.visitLabel(if_Lable);

}

public void visitInsn(int opcode){
if(opcode >= IRETURN && opcode <= RETURN){
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, "asmAop/asmAopInvoker",
"methodEnd", "(Ljava/lang/String;)I");
}
mv.visitInsn(opcode);
}
public void visitEnd() {
mv.visitLabel(try_catch_end);
mv.visitTryCatchBlock(try_catch_start, try_catch_end, try_catch_end, null);
mv.visitInsn(Opcodes.ATHROW);
mv.visitEnd();
}

public void visitMaxs(int maxStack,int maxLocals){
//保证max stack足够大
mv.visitMaxs(Math.max(EXCEPTION_STACK,maxStack), maxLocals);
}
}



所涉及类以打包。

代码运行环境 asm 3.3.1 jdk 1.6.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值