clase transformación no tiene ningún efecto

clankill3r:

Sobre la base de este tutorial que intenta conseguir un agente de Java para el trabajo. https://www.baeldung.com/java-instrumentation#loading-a-java-agent

Yo conseguir [Agent] Transforming class TestApplicationtengo ningún error, pero no puedo ver ningún efecto de transformar la clase.

Con el tiempo me gustaría conseguir tanto la carga estática y carga dinámica de trabajo, pero por ahora se centran en la forma estática.


public class Static_Agent {

    public static void premain(String agentArgs, Instrumentation inst) {
        String[] tokens = agentArgs.split(";");
        String className = tokens[0];
        String methodName = tokens[1];

        System.out.println(">> "+className);
        System.out.println(">> "+methodName);
        transformClass(className, methodName, inst);
    }



    public static void transformClass(String className, String methodName, Instrumentation instrumentation) {
        Class<?> targetCls = null;
        ClassLoader targetClassLoader = null;
        // see if we can get the class using forName
        try {
            targetCls = Class.forName(className);
            targetClassLoader = targetCls.getClassLoader();
            transform(targetCls, methodName, targetClassLoader, instrumentation);
            return;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // otherwise iterate all loaded classes and find what we want
        for(Class<?> clazz: instrumentation.getAllLoadedClasses()) {
            if(clazz.getName().equals(className)) {
                targetCls = clazz;
                targetClassLoader = targetCls.getClassLoader();
                transform(targetCls, methodName, targetClassLoader, instrumentation);
                return;
            }
        }
        throw new RuntimeException("Failed to find class [" + className + "]");
    }


    public static void transform(Class<?> clazz, String methodName, ClassLoader classLoader, Instrumentation instrumentation) {
        Transformer dt = new Transformer(clazz.getName(), methodName, classLoader);
        instrumentation.addTransformer(dt, true);
        try {
            instrumentation.retransformClasses(clazz);
        } catch (Exception ex) {
            throw new RuntimeException("Transform failed for class: [" + clazz.getName() + "]", ex);
        }
    }



}
public class Transformer implements ClassFileTransformer {


    /** The internal form class name of the class to transform */
    private String targetClassName;
    /** The class loader of the class we want to transform */
    private ClassLoader targetClassLoader;

    private String targetMethodName;

    public Transformer(String targetClassName, String targetMethodName, ClassLoader targetClassLoader) {
        this.targetClassName = targetClassName;
        this.targetClassLoader = targetClassLoader;
        this.targetMethodName = targetMethodName;
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] byteCode = classfileBuffer;

        String finalTargetClassName = this.targetClassName.replaceAll("\\.", "/");
        if (!className.equals(finalTargetClassName)) {
            return byteCode;
        }

        if (className.equals(finalTargetClassName) && loader.equals(targetClassLoader)) {
            System.out.println("[Agent] Transforming class TestApplication");
            try {

                ClassPool cp = ClassPool.getDefault();
                CtClass cc = cp.get(targetClassName);
                CtMethod m = cc.getDeclaredMethod(targetMethodName);
                m.addLocalVariable("startTime", CtClass.longType);
                m.insertBefore("startTime = System.currentTimeMillis();");

                StringBuilder endBlock = new StringBuilder();

                m.addLocalVariable("endTime", CtClass.longType);
                m.addLocalVariable("opTime", CtClass.longType);
                endBlock.append("endTime = System.currentTimeMillis();");
                endBlock.append("opTime = (endTime-startTime)/1000;");

                endBlock.append("System.out.println(\"[Application] Withdrawal operation completed in:\" + opTime + \" seconds!\");");

                m.insertAfter(endBlock.toString());

                byteCode = cc.toBytecode();
                cc.detach();
            } catch (Exception e) {
                System.out.println("Exception"+e);
            }
        }
        return byteCode;
    }
}
public class TestApplication {

    public static void main(String[] args) {

        try {
            TestApplication.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void run() throws Exception {
        System.out.println("--- start ---");

        while (true) {
            test();
            Thread.sleep(4_000);
        }


    }


    static int count = 0;

    public static void test() {
        System.out.println(count++);
    }

}

Pongo en marcha con:

java -javaagent:static_agent.jar="doeke.application.TestApplication;test" -jar application.jar

En caso de que ayuda, el proyecto está aquí: https://github.com/clankill3r/java_agent

Editar:

En el Transformer.java cerca del final del archivo que uso e.printStackTrace();ahora.

Obtuve el siguiente error:

[Agent] Transforming clase TestApplication javassist.NotFoundException: doeke.application.TestApplication en javassist.ClassPool.get (ClassPool.java:436) en doeke.transformer.Transformer.transform (Transformer.java:48) en java.instrument / java. lang.instrument.ClassFileTransformer.transform (ClassFileTransformer.java:246) en java.instrument / sun.instrument.TransformerManager.transform (TransformerManager.java:188) en java.instrument / sun.instrument.InstrumentationImpl.transform (InstrumentationImpl.java: 563) en java.instrument / sun.instrument.InstrumentationImpl.retransformClasses0 (Método nativo) en java.instrument / sun.instrument.InstrumentationImpl.retransformClasses (InstrumentationImpl.java:167) en doeke.static_agent.Static_Agent.transform (Static_Agent.java: 56) a doeke.static_agent.Static_Agent.transformClass (Static_Agent.java:34) en doeke.static_agent.Static_Agent.premain (Static_Agent.java:22) en java.base / jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Método Nativo) en java.base / jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) a java.base / jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) en java.base / java.lang.reflect.Method.invoke (Method.java:566) en java.instrument / sun.instrument. InstrumentationImpl.loadClassAndStartAgent (InstrumentationImpl.java:513) en java.instrument / sun.instrument.InstrumentationImpl.loadClassAndCallPremain (InstrumentationImpl.java:525)reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) en java.base / java.lang.reflect.Method.invoke (Method.java:566) en java.instrument / sun.instrument.InstrumentationImpl.loadClassAndStartAgent (InstrumentationImpl.java: 513) en java.instrument / sun.instrument.InstrumentationImpl.loadClassAndCallPremain (InstrumentationImpl.java:525)reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) en java.base / java.lang.reflect.Method.invoke (Method.java:566) en java.instrument / sun.instrument.InstrumentationImpl.loadClassAndStartAgent (InstrumentationImpl.java: 513) en java.instrument / sun.instrument.InstrumentationImpl.loadClassAndCallPremain (InstrumentationImpl.java:525)

--- comienzo ---

0

1

garykwwong:

Gracias por plantear esta cuestión que me permita tener la oportunidad de echar un vistazo de Java instrumentación.

Después de pasar algún tiempo para la comprobación cruzada de sus códigos de muestra y el tutorial proporcionado. El problema no es de los códigos de programación, pero la forma en cómo poner en marcha su programa.

Si agrega algunos registradores con el método transform () en Transformer.java, se encuentra que la ruta de código se rompe después de ejecutar:

ClassPool cp = ClassPool.getDefault();

Y, después de reemplazar la excepción captura de código en el mismo método a partir de:

} catch (Exception e) {

a:

} catch (NotFoundException | CannotCompileException | IOException e) {

Sería dar a sus más pistas de la siguiente manera:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(Unknown Source)
        at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: javassist/NotFoundException
        at doeke.static_agent.Static_Agent.transform(Static_Agent.java:60)
        at doeke.static_agent.Static_Agent.transformClass(Static_Agent.java:40)
        at doeke.static_agent.Static_Agent.premain(Static_Agent.java:28)
        ... 6 more
Caused by: java.lang.ClassNotFoundException: javassist.NotFoundException
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 9 more
FATAL ERROR in native method: processing of -javaagent failed

Hasta este punto, la causa raíz es más evidente. Es porque mientras que el lanzamiento del programa, esas clases pertinentes javassist (por ejemplo ClassPool, CtClass, CtMethod, etc.) no pueden referirse a sus bibliotecas correspondientes durante el tiempo de ejecución.

Por lo tanto, la solución es :

  1. Suponiendo que ha exportado el static_agent.jar en la misma carpeta "acumulación" a partir de application.jar

  2. toda otra estructura de carpetas siguen siendo los mismos, como se muestra en su github proporcionado

  3. vamos a "CD" a la acumulación carpeta en la consola de comandos

  4. la revisión del programa original lanzamiento de la escritura de la siguiente

El sistema operativo Windows:

java -javaagent:static_agent.jar="doeke.application.TestApplication;test" -cp ../libs/javassist-3.12.1.GA.jar;application.jar doeke.application.TestApplication

Unix / Linux OS:

java -javaagent:static_agent.jar="doeke.application.TestApplication;test" -cp ../libs/javassist-3.12.1.GA.jar:application.jar doeke.application.TestApplication

Se podría finalmente obtener su resultado esperado:

[Agent] In premain method.
>> doeke.application.TestApplication
>> test
[Agent] Transforming class
--- start ---
0
[Application] Withdrawal operation completed in:0 seconds!
1
[Application] Withdrawal operation completed in:0 seconds!

EDITAR

Además, quiero pegar algunos códigos con respecto a la forma de insertar códigos en medio de un método a través javassist.

En caso de que el método de ensayo () en TestApplication.java se cambia como:

line 30    public static void test() {
line 31        System.out.println(count++);
line 32        
line 33        System.out.println("Last line of test() method");
line 34    }

Supongamos que queremos añadir una línea entre el recuento y la ========= , digamos "Esta es la línea de separación", que el resultado se vería así:

1 
-- This is line separator -- 
Last line of test() method

Luego, en el método de transformación (...) de Transformer.java, podría agregar una línea de código como de abajo:

m.insertAt(32,"System.out.println(\"-- This is line separator --\");");

lo que hace que se convierte en:

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
        ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    byte[] byteCode = classfileBuffer;

    String finalTargetClassName = this.targetClassName.replaceAll("\\.", "/");
    if (!className.equals(finalTargetClassName)) {
        return byteCode;
    }

    if (className.equals(finalTargetClassName) && loader.equals(targetClassLoader)) {
        System.out.println("[Agent] Transforming class TestApplication");
        try {
            // Step 1 Preparation
            ClassPool cp = ClassPool.getDefault();
            CtClass cc = cp.get(targetClassName);
            CtMethod m = cc.getDeclaredMethod(targetMethodName);

            // Step 2 Declare variables
            m.addLocalVariable("startTime", CtClass.longType);
            m.addLocalVariable("endTime", CtClass.longType);
            m.addLocalVariable("opTime", CtClass.longType);

            // Step 3 Insertion of extra logics/implementation
            m.insertBefore("startTime = System.currentTimeMillis();");

            m.insertAt(32,"System.out.println(\"-- This is line separator --\");");

            StringBuilder endBlock = new StringBuilder();

            endBlock.append("endTime = System.currentTimeMillis();");
            endBlock.append("opTime = (endTime-startTime)/1000;");
            endBlock.append("System.out.println(\"[Application] Withdrawal operation completed in:\" + opTime + \" seconds!\");");

            m.insertAfter(endBlock.toString());

            // Step 4 Detach from ClassPool and clean up stuff
            byteCode = cc.toBytecode();
            cc.detach();
        } catch (NotFoundException | CannotCompileException | IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    return byteCode;
}

Por último, sería obtener un resultado como el de abajo de imprimir el código en el medio de un método:

[Agent] In premain method.
className=doeke.application.TestApplication
methodName=test
>> doeke.application.TestApplication
>> test
[Agent] Transforming class TestApplication
--- start ---
0
-- This is line separator --
=========
[Application] Withdrawal operation completed in:0 seconds!
1
-- This is line separator --
=========
[Application] Withdrawal operation completed in:0 seconds!
2
-- This is line separator --
=========
[Application] Withdrawal operation completed in:0 seconds!

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=311660&siteId=1
Recomendado
Clasificación