1

I have a WebApplication in Java that has 3 threads which just sends some data to a program that calls the application and saves data (log files from log4j) to a h2 database.

Now I don't want to have 3 threads which are more or less the same. So I'm trying to inject the code with javassist and an Agent after some tries I think I will get the result I want! so if my code is right( I'll post it later would be nice if you could take a look) some bytecode will be inserted to my 3 thread Methods before they get called but....

I used this tutorial http://appcrawler.com/wordpress/2013/01/02/simple-byte-code-injection-example-with-javassist/

and if I want to call my Application I need to write java -javaagent:myAgent.jar foo so says the tutorial but my webApplication gets called by an other java program can I just call it now and my Agent which inserts the Bytecode will work? Probably not, I think. so it would be nice if you could tell me how to do that or maybe how to advance my code so that I don't need it.

Code: My Transform class (bytecode gets inserted)

public class MyTransformer implements ClassFileTransformer {


    @Override
    public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {

        return transformClass(redefiningClass, bytes);
    }

    private byte[] transformClass(Class classToTransform, byte[] b) {
        ClassPool pool = ClassPool.getDefault();
        CtClass cl = null;
        try {
            cl = pool.get("de.test.ws.MyApplication");
        } catch (javassist.NotFoundException e) {
            e.printStackTrace();
        }
        try {

            assert cl != null;
            CtMethod[] methods = cl.getMethods();
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].isEmpty() == false) {
                    changeMethod(methods[i]);
                }
            }
            b = cl.toBytecode();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cl != null) {
                cl.detach();
            }
        }
        return b;
    }

    private void changeMethod(CtMethod method) throws NotFoundException, CannotCompileException {

        if (method.hasAnnotation(Loggable.class)) {

            method.insertBefore("  Thread thread0 = new Thread(new Runnable() {\n" +
                    "\n" +
                    "            @Override\n" +
                    "            public void run() {\n" +
                    "\n" +
                    "\n" +
                    "                try {\n" +
                    "                    threadLogger.logCall(Webservice.class.getMethod(\"startThread0\"),\"Thread0\");\n" +
                    "                } catch (Exception e) {\n" +
                    "                    e.printStackTrace();\n" +
                    "                }\n" +
                    "            }\n" +
                    "        });\n" +
                    "        thread0.start();");
        }
    }
}
Holger
  • 285,553
  • 42
  • 434
  • 765
alovaros
  • 476
  • 4
  • 23
  • 1
    Then you’ll have to convince that other application to launch the jvm with agents. Or, you resort to later-on attaching, i.e. [using `agentmain` rather than `premain`](http://docs.oracle.com/javase/8/docs/api/?java/lang/instrument/package-summary.html). Unless your webapp runs in a too restricted environment, it may trigger the loading of the agent itself. At the end of [this answer](http://stackoverflow.com/a/19912148/2711488) is a piece of code which attaches to its own JVM and loads itself as an agent. It should be adaptable to load other agents easily. – Holger Jul 22 '15 at 18:13
  • So first thank you for your comment :D but I'm a ral noob in java and I have no idea what da hell your code do o.o so more or less I understood something but it's much code for a little developer xd – alovaros Jul 23 '15 at 12:34
  • Well, the [Instrumentation package documentation](http://docs.oracle.com/javase/8/docs/api/?java/lang/instrument/package-summary.html) describes under “Starting Agents After VM Startup” the prerequisites for allowing a jar-based agent to be started later-on but tells the initiation as implementation specific. So one way that works with Oracle’s JVM is the [Attach API](http://docs.oracle.com/javase/8/docs/jdk/api/attach/spec/index.html) using the `loadAgent` method. I’m afraid, there’s no easier method when it comes to loading after startup. – Holger Jul 23 '15 at 14:14

0 Answers0