这样的错误竟然能得到正确的值,这个bug藏的够深的。

为了统计方法执行时候,我用ASM在方法开始的时候插入一个变量startLocal记录开始执行的时间,然后在结束的时间用当前时间去差这个开始时间,为了调试,我同时又插入了一个endLocal

/** * Project: dragoon-common-2.5.3 * * File Created at 2011-5-5 * $Id$ * * Copyright 1999-2100 Alibaba.com Corporation Limited. * All rights reserved. * * This software is the confidential and proprietary information of * Alibaba Company. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Alibaba.com. */ package com.alibaba.instrumention.classop; import com.alibaba.citrus.asm.MethodVisitor; import com.alibaba.citrus.asm.Opcodes; import com.alibaba.citrus.asm.Type; import com.alibaba.citrus.asm.commons.AdviceAdapter; /** * Comment of InstrumtionAdviceAdapter * * @author axman.wang */ public class InstrumentionAdviceAdapter extends AdviceAdapter { private String methodName; //private int access; private String className; private int startLocal; private int endLocal; protected InstrumentionAdviceAdapter(MethodVisitor mv, int access, String methodName, String desc, String signature, String[] exceptions,String className) { super(mv, access, methodName, desc); this.methodName = methodName; //this.access = access; this.className = className; } protected void onMethodEnter() { this.mv.visitLdcInsn(className + "." + methodName); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "before", "(Ljava/lang/String;)V"); this.startLocal = this.newLocal(Type.getType(Long.class)); this.endLocal = this.newLocal(Type.getType(Long.class)); this.mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); this.mv.visitVarInsn(LSTORE, startLocal); //log this.mv.visitVarInsn(LLOAD, startLocal); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "currentTime", "(J)V"); //end log } protected void onMethodExit(int opcode) { this.mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); this.mv.visitVarInsn(LSTORE, endLocal); //log this.mv.visitVarInsn(LLOAD, startLocal); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "currentTime", "(J)V"); //end log //log this.mv.visitVarInsn(LLOAD, endLocal); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "currentTime", "(J)V"); //end log this.mv.visitVarInsn(LLOAD, endLocal); this.mv.visitVarInsn(LLOAD, startLocal); this.mv.visitInsn(LSUB); this.mv.visitLdcInsn(className + "." + methodName); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "after", "(JLjava/lang/String;)V"); } }

注意这段有bug的代码竟然可以正确地执行了。但是当我去掉调示后,改成这样:

/** * Project: dragoon-common-2.5.3 * * File Created at 2011-5-5 * $Id$ * * Copyright 1999-2100 Alibaba.com Corporation Limited. * All rights reserved. * * This software is the confidential and proprietary information of * Alibaba Company. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Alibaba.com. */ package com.alibaba.instrumention.classop; import com.alibaba.citrus.asm.MethodVisitor; import com.alibaba.citrus.asm.Opcodes; import com.alibaba.citrus.asm.Type; import com.alibaba.citrus.asm.commons.AdviceAdapter; /** * Comment of InstrumtionAdviceAdapter * * @author axman.wang */ public class InstrumentionAdviceAdapter extends AdviceAdapter { private String methodName; //private int access; private String className; private int startLocal; protected InstrumentionAdviceAdapter(MethodVisitor mv, int access, String methodName, String desc, String signature, String[] exceptions,String className) { super(mv, access, methodName, desc); this.methodName = methodName; //this.access = access; this.className = className; } protected void onMethodEnter() { this.mv.visitLdcInsn(className + "." + methodName); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "before", "(Ljava/lang/String;)V"); this.startLocal = this.newLocal(Type.getType(Long.class)); this.mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); this.mv.visitVarInsn(LSTORE, startLocal); } protected void onMethodExit(int opcode) { this.mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); this.mv.visitVarInsn(LLOAD, startLocal); this.mv.visitInsn(LSUB); this.mv.visitLdcInsn(className + "." + methodName); this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/alibaba/instrumention/classop/InstrumentionStat", "after", "(JLjava/lang/String;)V"); } }

却得不到正确的结果了。于是反复查看地,终于发现了

this.startLocal = this.newLocal(Type.getType(Long.class));

应该是:

this.startLocal = this.newLocal(Type.LONG_TYPE);

如果开始分配的栈不对,两个object的栈相当于一个long的栈,但在LSUB的时候为什么是正确的?

两个Long对象进行lsub,虽然java源码在编译的时候可以自动插入转换指令,但在上面的字节码指令中

仍然可以正确LSUB,虽然栈中的值是正确的,但却越过了类型检查。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值