Вызов метода Java javassist

Итак, я использую java-агент с javassist для внедрения небольшого кода, связанного с мониторингом, в разные методы в разных классах.

Мой код агента Java:

public class ConverterAgent implements ClassFileTransformer {

public static void premain(String args, Instrumentation instrumentation){
    System.out.println(">>>>>>>>>> Intializing Java agent <<<<<<<<<<");
    ConverterAgent transformer = new ConverterAgent();
    instrumentation.addTransformer(transformer);

}

public static void agentmain(String args, Instrumentation instrumentation){
    System.out.println(">>>>>>>>>> Intializing Java agent <<<<<<<<<<");
    ConverterAgent transformer=new ConverterAgent();
    instrumentation.addTransformer(transformer); 
}


@Override
public byte[] transform(final ClassLoader loader, 
        String className, 
        Class<?> classBeingRedefined, 
        ProtectionDomain protectionDoman, 
        byte[] classFileBuffer)
                throws IllegalClassFormatException {



//javassist code goes here


return classFileBuffer;

}

}

И мои javassist инъекции выглядят так:

if ("className1".equals(className)){

//code

}


 if ("className2".equals(className)){

//same code as in first class

}


if ("className3".equals(className)){

//same code as in first and second class

}

Итак, я ввожу один и тот же код несколько раз, я хочу оптимизировать свой процесс и вызывать метод для каждой инъекции, чтобы мне не приходилось копировать один и тот же код снова и снова. Но вот где я столкнулся со своей проблемой, какой тип метода я должен использовать и какие аргументы ему нужны, кроме имен классов и методов.


person stef    schedule 06.03.2017    source источник


Ответы (1)


В методе преобразования вы берете байт-код класса, а затем возвращаете новый байт-код класса с вашими изменениями.

Это означает, что вы наверняка вернете byte[], содержащий информацию, необходимую для метода преобразования.

Итак, ваш метод должен быть примерно таким:

public class DynamicTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
    ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        byte[] byteCode = classfileBuffer;

        // into the transformer will arrive every class loaded so you filter 
        // to match only what you need
        if (className.equals("com/full/path/to/be/instrumented/className1") ||
            className.equals("com/full/path/to/be/instrumented/className2") ||
            className.equals("com/full/path/to/be/instrumented/className3") ) {

            byteCode = myMethodThatTransform(className, byteCode);
        }

        return byteCode;
    }


    public byte[] myMethodThatTransform(String className, byte[] byteCode){\
        try {
            // retrive default Javassist class pool
            ClassPool cp = ClassPool.getDefault();
            // get from the class pool our class with this qualified name
            CtClass cc = cp.get(className);
            // get all the methods of the retrieved class
            CtMethod[] methods = cc.getDeclaredMethods()
            for(CtMethod meth : methods) {
                // The instrumentation code to be returned and injected
                final StringBuffer buffer = new StringBuffer();
                String name = meth.getName();
                // just print into the buffer a log for example
                buffer.append("System.out.println(\"Method " + name + " executed\" );");
                meth.insertBefore(buffer.toString())
            }
            // create the byteclode of the class
            byteCode = cc.toBytecode();
            // remove the CtClass from the ClassPool
            cc.detach();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return byteCode;
    }
}
person rakwaht    schedule 06.03.2017
comment
Было бы намного эффективнее, если бы вы использовали карту, а не несколько проверок на равенство, разделенных || - person Sean Patrick Floyd; 06.03.2017
comment
Большое спасибо, вы решили мою проблему, я уверен, что кто-то еще найдет ваш код очень полезным. - person stef; 06.03.2017