Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java javassist方法调用_Java_Methods_Code Injection_Javassist_Javaagents - Fatal编程技术网

Java javassist方法调用

Java javassist方法调用,java,methods,code-injection,javassist,javaagents,Java,Methods,Code Injection,Javassist,Javaagents,因此,我将java代理与javassist结合使用,目的是向不同类中的不同方法注入一些与监控相关的小代码 我的java代理代码: public class ConverterAgent implements ClassFileTransformer { public static void premain(String args, Instrumentation instrumentation){ System.out.println(">>>>>>

因此,我将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;

}

}
所以我多次注入相同的代码,我想优化我的过程,并为每次注入调用一个方法,这样我就不必一遍又一遍地复制相同的代码。但这里是我遇到问题的地方,我应该使用什么方法类型,除了类和方法名之外,它还需要什么参数

在转换方法中,您使用类字节码,然后返回带有修改的“新”类字节码。 这意味着您要返回的肯定是包含转换方法所需信息的字节[]

所以你的方法应该是这样的:

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

如果您使用的是一个映射,而不是由| |分隔的多个相等检查,那么效率会更高。非常感谢,您解决了我的问题,我相信其他人也会发现您的代码非常有用。
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;
    }
}