如何使用Javassist制作数组列表

2022-09-02 14:03:39

我想在检测期间将arrayList添加到方法中。我尝试了一下,如(Javassist在尝试添加一行来创建Map时不能CompileException)所述,但它会抛出一个不同的java.lang.VerifyError异常。

    public void createInsertBefore(String scenarioName, String className, CtMethod method,
                                   String insertBefore) throws CannotCompileException {
        method.addLocalVariable("startTime", CtClass.longType);
        StringBuilder bBuilder = new StringBuilder();
        bBuilder.append("startTime = System.nanoTime();");
        bBuilder.append("System.out.println(startTime);");

        if((insertBefore!=null) && !insertBefore.isEmpty()){
            bBuilder.append(insertBefore);
        }

        bBuilder.append("java.util.List metadata = new java.util.ArrayList();");

        System.out.println(bBuilder.toString());
        method.insertBefore(bBuilder.toString());
}

从 print 语句接收的输出为:

startTime = System.nanoTime();
System.out.println(startTime);
java.util.List metadata = new java.util.ArrayList();

但它会引发以下异常,

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:397)
Caused by: java.lang.VerifyError
    at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
    at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
    at org.wso2.das.javaagent.instrumentation.Agent.premain(Agent.java:57)
    ... 6 more
FATAL ERROR in native method: processing of -javaagent failed
Aborted (core dumped)

情况与之前相同,但为什么会引发不同的异常。我做错了什么...请帮忙...

更新 1

行添加(我已经删除了一些打印行),插入之前

 startTime = System.nanoTime();
 java.util.List metadata = new java.util.ArrayList();

插入

System.out.println("prepareStatement is running");
java.util.Map/*<String,String>*/ arbitraryMap = new java.util.HashMap/*String,String>*/();
arbitraryMap.put("query",$1);System.out.println(arbitraryMap);

插入后

System.out.println(System.nanoTime()-startTime);

答案 1

当 VM 注意到已编译的字节码无效时,将发生 。例如,当您尝试使用整数或类似事物的加载指令读取长变量时。VerifyError

因此,在你的例子中,代码编译,javaassist发挥了它的魔力,但VM不接受代码。它必须是 javassist 中的 bug 或用法中的 bug。

如何修复它:

1)据我所知,您只能在方法的开头添加一个语句(而不是一行)。如果要添加多个,请将它们括在大括号中,例如insertBefore{}method.insertBefore("{" + bBuilder.toString() + "}");

2) 您没有像使用时那样将元数据添加为变量startTime

X) 如果此错误或其他错误仍然存在,请尝试将类文件写入磁盘上的文件(使用时可以作为访问修改后的类文件)。然后,您可以使用javap等工具来查看编译的代码,并更清楚地看到发生了什么。toClassFilebyte[]


答案 2

推荐