Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a ArrayList using Javassist

I want to add a arrayList into a method during instrumentation. I tried it as mentioned in (Javassist CannotCompileException when trying to add a line to create a Map) but it throws a different exception with a 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());
}

Output received from the print statement is,

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

But it throws following exception,

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)

The situation is same as earlier, but why does it throw a different exception. What am i doing wrong....some help please...

Update 1

lines added with (I have removed some print lines), insertBefore,

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

insertAt

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);

insertAfter

System.out.println(System.nanoTime()-startTime);
like image 481
udani Avatar asked Oct 23 '15 10:10

udani


1 Answers

A VerifyError occurs when the VM notices, that an already compiled bytecode is not valid. For example, when you try to read a long variable using a load instruction for an integer, or similar things.

So, in your case, the code compiles, javaassist does its magic, but the VM does not accept the code. It must be either a bug in javassist or a bug in its usage.

How to fix it:

1) As far as I know, you can only add one statement (not one line) at the beginning of a method using insertBefore. If you want to add more than one, wrap them in braces {}, something like method.insertBefore("{" + bBuilder.toString() + "}");

2) You did not add the metadata as a variable like you did with startTime

X) If this or another error still persists, try to write the class file to a file on disk (using toClassFile you can access the modified class file as a byte[]). Then you can use tools like javap to look at the compiled code, and see more clearly what is going on.

like image 90
loonytune Avatar answered Oct 06 '22 18:10

loonytune