有解决办法吗?当使用@Binding.InvokeArgs Object[] args时抛异常,急需使用,感谢求解~~
java.lang.IllegalArgumentException: Error at instruction 21: Expected an object reference, but found . test()V 00000 R . . . : : L0 00001 R . . . : : LINENUMBER 23 L0 00002 R . . . : : NEW com/alibaba/bytekit/asm/interceptor/AtInvokeTest2$Sample 00003 R . . . : R : DUP 00004 R . . . : R R : INVOKESPECIAL com/alibaba/bytekit/asm/interceptor/AtInvokeTest2$Sample. ()V 00005 R . . . : R : ASTORE 1 00006 R R . . : : L1 00007 R R . . : : LINENUMBER 24 L1 00008 R R . . : : ICONST_0 00009 R R . . : I : ISTORE 2 00010 R R I . : : L2 00011 R R I . : : FRAME APPEND [com/alibaba/bytekit/asm/interceptor/AtInvokeTest2$Sample I] 00012 R R I . : : ILOAD 2 00013 R R I . : I : ICONST_1 00014 R R I . : I I : IF_ICMPGE L3 00015 R R I . : : L4 00016 R R I . : : LINENUMBER 25 L4 00017 R R I . : : ALOAD 1 00018 R R I . : R : LDC "hello2" 00019 R R I . : R R : ILOAD 2 00020 R R I . : R R I : LDC "hello" 00021 R R I . : R R I R : ALOAD 3 00022 ? : INVOKESTATIC com/alibaba/bytekit/asm/interceptor/AtInvokeTest2$TestAccessInterceptor.onInvoke (Ljava/lang/String;[Ljava/lang/Object;)V 00023 ? : INVOKEVIRTUAL com/alibaba/bytekit/asm/interceptor/AtInvokeTest2$Sample.hello (Ljava/lang/String;I)Ljava/lang/String; 00024 ? : POP 00025 ? : L5 00026 ? : LINENUMBER 24 L5 00027 ? : IINC 2 1 00028 ? : GOTO L2 00029 R R I . : : L3 00030 R R I . : : LINENUMBER 27 L3 00031 R R I . : : FRAME SAME 00032 R R I . : : RETURN 00033 ? : L6
给出具体的复现demo。
给出具体的复现demo。
运行com.alibaba.bytekit.asm.interceptor.AtInvokeTest2中的testcase就可以复现:
给出具体的复现demo。
能帮忙解决吗,等着用,感谢
这个测试是有问题,默认应该是不启用的,可以看项目说明,用 mvn命令来执行。
给出具体的复现demo。
能帮忙解决吗,等着用,感谢
请问下您这个问题解决了么?我用@Binding.InvokeReturn也会出错。
这个测试是有问题,默认应该是不启用的,可以看项目说明,用 mvn命令来执行。
是不是这两个Binding, InvokeRetuer, InvokeArgs现在还不能用呢?
这个测试是有问题,默认应该是不启用的,可以看项目说明,用 mvn命令来执行。
复现demo:MicroService类中方法interfaceA调用了方法interfaceB,期望得到传入interfaceB的参数值
package com.example;
import com.alibaba.bytekit.asm.MethodProcessor;
import com.alibaba.bytekit.asm.binding.Binding;
import com.alibaba.bytekit.asm.interceptor.InterceptorProcessor;
import com.alibaba.bytekit.asm.interceptor.annotation.AtInvoke;
import com.alibaba.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser;
import com.alibaba.bytekit.utils.AgentUtils;
import com.alibaba.bytekit.utils.AsmUtils;
import com.alibaba.bytekit.utils.Decompiler;
import com.alibaba.deps.org.objectweb.asm.tree.ClassNode;
import com.alibaba.deps.org.objectweb.asm.tree.MethodNode;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class InterfaceInvokeDemo {
public static class MicroService {
public void interfaceA(String strA){
System.out.println("interfaceA" + strA);
String strb = strA + "BBB";
interfaceB(strb);
}
public void interfaceB(String strB){
System.out.println("interfaceB" + strB);
}
}
public static class TestAccessInterceptor {
@AtInvoke(name = "interfaceB", inline = false, whenComplete = false)
public static void onInvokeAfter(
@Binding.This Object object,
@Binding.Class Object clazz,
@Binding.MethodName String methodName,
@Binding.InvokeMethodName String invokeMethodName,
@Binding.InvokeArgs Object[] args,
@Binding.InvokeReturn Object invokeReturn,
@Binding.InvokeMethodDeclaration String declaration
) {
System.err.println("onInvokeAfter: this" + object);
System.err.println("methodName: " + methodName);
System.err.println("InvokeMethodName: " + invokeMethodName);
System.err.println("InvokeMethodDeclaration: " + declaration);
}
}
public static void main(String[] args) throws Exception {
AgentUtils.install();
// 不断执行
final MicroService microService = new MicroService();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; ++i) {
try {
TimeUnit.SECONDS.sleep(5);
microService.interfaceA(String.valueOf(i));
System.out.println("call interfaceA result");
} catch (Throwable e) {
System.out.println("exception: " + e.getMessage());
}
}
}
});
thread.start();
// 拦截器定义
DefaultInterceptorClassParser defaultInterceptorClassParser = new DefaultInterceptorClassParser();
List<InterceptorProcessor> interceptorProcessor = defaultInterceptorClassParser.parse(TestAccessInterceptor.class);
// 加载字节码
ClassNode classNode = AsmUtils.loadClass(MicroService.class);
// 通过拦截器对字节码增强
for (MethodNode methodNode : classNode.methods) {
if (methodNode.name.equals("interfaceA")) {
MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode);
for (InterceptorProcessor interceptor : interceptorProcessor) {
interceptor.process(methodProcessor);
}
}
}
// 增强后的字节码
byte[] bytes = AsmUtils.toBytes(classNode);
// 查看反编译结果
System.out.println(Decompiler.decompile(bytes));
// 等待,查看增强前的反编译结果
TimeUnit.SECONDS.sleep(10);
// 增强类
AgentUtils.reTransform(MicroService.class, bytes);
System.in.read();
}
}
统一说下有问题的原因:
- 从原理上来说,获取到 invoke method 前的 args ,想要在 invoke method 之后再取出来。它实际上是保存到了一个临时变量里,也就是一个 数组里
- 同时,如果想要获取 invoke method 的返回值,并且在后续获取到,那么它实际上也是保存到了一个 临时变量 里
- 但目前这种方式有问题: jvm 会抛异常字节码校验失败 ,可能要在 jvm 启动时增加不要校验字节码的参数
- 所以实际上 拦载 invoke method 获取 args / return value 不太成熟
- 另外,因为这种操作实际上是对 jvm 调用栈有修改,目前是只支持保存一个 slot ,所以 不能同时保存 invoke method 的 args 和 invoke method return value 。 只能用一个注解。
统一说下有问题的原因:
- 从原理上来说,获取到 invoke method 前的 args ,想要在 invoke method 之后再取出来。它实际上是保存到了一个临时变量里,也就是一个 数组里
- 同时,如果想要获取 invoke method 的返回值,并且在后续获取到,那么它实际上也是保存到了一个 临时变量 里
- 但目前这种方式有问题: jvm 会抛异常字节码校验失败 ,可能要在 jvm 启动时增加不要校验字节码的参数
- 所以实际上 拦载 invoke method 获取 args / return value 不太成熟
- 另外,因为这种操作实际上是对 jvm 调用栈有修改,目前是只支持保存一个 slot ,所以 不能同时保存 invoke method 的 args 和 invoke method return value 。 只能用一个注解。
从测试结果来看,即使只使用invoke method 的 args一个注解,也会出现失败,提示读了未初始化的局部变量:
public static class TestAccessInterceptor {
@AtInvoke(name = "interfaceB", inline = false, whenComplete = false)
public static void onInvokeAfter(
@Binding.This Object object,
@Binding.Class Object clazz,
@Binding.MethodName String methodName,
@Binding.InvokeMethodName String invokeMethodName,
@Binding.InvokeArgs Object[] args,
//@Binding.InvokeReturn Object invokeReturn,
@Binding.InvokeMethodDeclaration String declaration
) {
System.err.println("onInvokeAfter: this" + object);
System.err.println("methodName: " + methodName);
System.err.println("InvokeMethodName: " + invokeMethodName);
System.err.println("InvokeMethodDeclaration: " + declaration);
}
}
public static class InterfaceInvokeDemo.MicroService { /* * Exception decompiling / public void interfaceA(String strA) { / * This method has failed to decompile. When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file. * * java.lang.IllegalStateException: Invisible function parameters on a non-constructor (or reads of uninitialised local variables). * at org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.assignSSAIdentifiers(Op02WithProcessedDataAndRefs.java:1637) * at org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.discoverStorageLiveness(Op02WithProcessedDataAndRefs.java:1877) * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:460) * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:278) * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:201) * at org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94) * at org.benf.cfr.reader.entities.Method.analyse(Method.java:531) * at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1042) * at org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:929) * at org.benf.cfr.reader.Driver.doClass(Driver.java:84) * at org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:75) * at com.alibaba.bytekit.utils.Decompiler.decompile(Decompiler.java:145) * at com.alibaba.bytekit.utils.Decompiler.decompile(Decompiler.java:40) * at com.example.InterfaceInvokeDemo.main(InterfaceInvokeDemo.java:95) */ throw new IllegalStateException("Decompilation failed"); }
public void interfaceB(String strB) {
System.out.println("interfaceB" + strB);
}
}
Process finished with exit code -1