Yes, it would be possible to have your custom classloader to load a class and through bytecode manipulation tools such as Javassist or ASM perform the modifications, loading into memory not the bytecode in the class file but rather the modified one.
Although there are easier (and better, in my opinion) ways of doing it.
Annotation Processor Tool (APT)
Since Java 6 you have APT which allows you to hook into the compiling process (via -processor
argument in javac). With APT you have access to the code's AST (Abstract Syntax Tree) and you can perform modifications directly when compiling using the javax.lang.model. This means that your class file will be generated with the needed modifications.
In this case the chain would be something like something like:
source -(compile and performs modifications at model level)-> bytecode already modified - regular class loader -> loads class into memory
Post-Compiling processing
Another approach which can be used is to perform bytecode injection after compilation as a post-compiling process. In this cases you use bytecode modification tools (once again javassist, asm, among others), which can perform the modifications you need when the desired annotation is found, generating a new class file with the injected bytecode.
In such case your chain would be:
source -compile -> bytecode -post-compile-> modified bytecode - regular class loader -> loads class into memory
Runtime modifications
Finally we reach runtime bytecode modifications. Even though your idea is possible, in my opinion I would leave the class loader magic and use tools such has Javassist that also allows you to have dynamic proxies which can be modified and reloaded.
In javassist particular case the chain would be
source -compile -> bytecode -post-compile-> modified bytecode - regular class loader -> loaded into memory - javassist proxy -> modified class - javassist hot swapper -> re-modified class
Proxies aren't perfect though (well nothing is). You'll have a performance hit and you won't be able to modify the public interface of your class (sidenote: both APT and post-compile process can allow you to modify the class public interface). I could go on a bit more on this, but I think this is already enough information to give you food for thought. Feel free to leave a comment if you need additional information.