Search code examples
javajvmbytecodejavaagentsbytecode-manipulation

How to manipulate a class' bytecode just before it is loaded?


I am trying to find a way to manipulate the bytecode of a class (at runtime) just before it is loaded. I need to do this because the manipulation depends on something that is not present before main (and potentially before the subject class is loaded).

I already looked at java agents. The premain method is obviously not applicable here, because it is executed before main, which means it can't depend on something that is set up in main. The other option seems to be agentmain and manually loading the agent at runtime. Now the problem with this is that in the newer versions (9+), the dependencies needed to do that (tools.jar) don't seem to be present anymore.

Now, I'd like to know what would be the best way to manipulate bytecode at a specific point in runtime or just before a class is loaded and if that is still possible somehow with Java 9+.


Solution

  • The premain method is obviously not applicable here, because it is executed before main, which means it can't depend on something that is set up in main

    This is not true. The agent does not need to modify the class bytecode right at the agent load time. It may just register ClassFileTransformer and postpone bytecode manipulation until the target class is loaded later. Alternatively an agent can simply save Instrumentation instance to be used later at any convenient moment of time.

    in the newer versions (9+), the dependencies needed to do that (tools.jar) don't seem to be present anymore

    This is also not quite correct. Attach API exists in all new versions of JDK. Since JDK 9 it no longer requires tools.jar, instead it belongs to jdk.attach module.

    To facilitate attach in runtime you may use byte-buddy-agent or a standalone jattach utility. Both work with JDK 8- as well as with JDK 9+.