Search code examples
javajavassist

instrumented method with javassist


I'm trying to write the name of the method into a file by adding few lines of code into each instrumented methods. I'm using Javassist.

Here's my code:

public static void addInstrumentation(CtClass ctClass, CtMethod ctMethod) throws NotFoundException, CannotCompileException {
    if (ctClass.getName().startsWith("com.application.bookstore.entities.test")) {
        String testName = ctClass.getName() + "." + ctMethod.getName();
        String fileToWrite = "C:/profiler/root.txt";
        ctMethod.insertBefore("{ FileWriter fw = new FileWriter(\"" + fileToWrite + "\", true); BufferedWriter out = new BufferedWriter(fw); out.write(\"" + testName + "\"); out.newLine(); out.close(); }");
    }
    else {
        String methodName = ctClass.getName() + "." + ctMethod.getName() + "()";
        String fileToRead = "C:/profiler/root.txt";
        ctMethod.insertBefore("{ FileReader fr = new FileReader(\"" + fileToRead + "\"); BufferedReader in = new BufferedReader(fr); String line; while((line = in.readLine()) != null); in.close();  FileWriter fw = new FileWriter(line, true); BufferedWriter out = new BufferedWriter(fw); out.write(\"" + methodName + "\"); out.newLine(); out.close(); }");
    }
}



/**
 * Get current classname and for each methods inside it, call the addInstrumentation method.
 */
@Override
public void onLoad(ClassPool pool, String classname) throws NotFoundException, CannotCompileException {
    if (classToImplement(classname))
    {
        pool.importPackage("java.io");
        CtClass ctClass = pool.get(classname);          


        for (CtMethod ctMethod : ctClass.getDeclaredMethods()) {
           if (!Modifier.isNative(ctMethod.getModifiers())) {
               addInstrumentation(ctClass, ctMethod);
           }
        }
    }
}

My problem is in the else part. I can't get the value of line and so open the file and write into it.

So, have you an idea about how to retrieve the value of line ?

Thanks


Solution

  • You could use a static String and keep the last value of testName. For a single thread you'll get the same result. For multiple threads it's a different story, but I guess that you're trying to get the stack trace for your tests and you run it sequential, so you should be safe. E.g.:

    Let's say you have a class

    com.application.bookstore.entities.test.ClassWithTheStaticField
    

    which has:

    public static String lastTestMethod;
    

    You can modify addInstrumentation like this:

    public static void addInstrumentation(CtClass ctClass, CtMethod ctMethod) throws NotFoundException, CannotCompileException {
        if (ctClass.getName().startsWith("com.application.bookstore.entities.test")) {
            String testName = ctClass.getName() + "." + ctMethod.getName();
            String fileToWrite = "C:/profiler/root.txt";
            ctMethod.insertBefore("{ com.application.bookstore.entities.test.ClassWithTheStaticField.lastTestMethod = " + testName + "; FileWriter fw = new FileWriter(\"" + fileToWrite + "\", true); BufferedWriter out = new BufferedWriter(fw); out.write(\"" + testName + "\"); out.newLine(); out.close(); }");
        }
        else {
            String methodName = ctClass.getName() + "." + ctMethod.getName() + "()";
            String fileToRead = "C:/profiler/root.txt";
            ctMethod.insertBefore("{ FileWriter fw = new FileWriter(com.application.bookstore.entities.test.ClassWithTheStaticField.lastTestMethod, true); BufferedWriter out = new BufferedWriter(fw); out.write(\"" + methodName + "\"); out.newLine(); out.close(); }");
        }
    }