From what I understand:
- to make AOP work, there is a need to modify the byte codes of your standard java class/object (often called "POJO" = Plain old Java object")
This is so that the AOP "advice" can be inserted
There are two ways to do this, by using a special compiler (like aspectJ's ajc) at compile time, or by manipulating the byte codes when the class is loaded (dynamically at run time in the class loader)
JBoss is using the second approach, so it is necessary to use a special class loader.
See my other post for some unscientific timings of JBoss AOP vs AspectJ.
Hope this helps,
thanks a lot for your reply. My understanding was that one can instrument byte code with regular compiler, I thought you can do this with javassist. Is it wrong?
With a regular ClassLoader and with Javassist you can instrument byte code. But you have to do with Java code.
The JBoss AOP Custom ClassLoader allows the xml configuration of the aspects. By using this ClassLoader the instrumentation is done automagically based on the xml configuration file.
Can't one instrument byte code base on the xml configuration that specifies what and how to instrument? Why there is a need in doing it at load time?
Thanks a lot for a response.
You must instrument classes at load-time, because aspects definition must be applied before the class is made available to the JVM. That's why there is a custom class loader.
Another advantage of the JBoss ClassLoader and the XML configuration file is the ability to specify many aspects and patterns where they apply :
- an aspect can apply to a class, a group of class or a package.
- an advice can apply on constructor or getter/setter methods
You can also made a class Advisable without applying advice on it, and their later in the code, attach advice to it dynamically. But for that, the class definition must altered when loaded by the ClassLoader.
thanks a lot for responding!
You must instrument classes at load-time, because aspects definition must be applied before the class is made available to the JVM.
Even without custom class loader byte code is instrumented before the class is made available to JVM. Can you comment this?
Can you be more precise and give a concrete example of instrumentation without custom ClassLoader ?
I think they're asking:
If you can modify the bytecode in place, why do you have to put it into a classloader to "publish" it to the JVM? Is it really an official piece of Java code after the bytecode has been changed?
Theoretically (and I may be completely wrong) the class you instrument has already been loaded into the classloader.
So the steps seem to be currently:
1. Load POJO.
2. Instrument POJO.
3. Re-load POJO.
Is this correct?
> I think they're asking:
> If you can modify the bytecode in place, why do you
> have to put it into a classloader to "publish" it to
> the JVM? Is it really an official piece of Java code
> after the bytecode has been changed?
It is exactly that, you cannot modify bytecode of an existing class at runtime. And yes, the modified piece of JavaCode is official.
> Theoretically (and I may be completely wrong) the
> class you instrument has already been loaded into the
> So the steps seem to be currently:
> 1. Load POJO.
> 2. Instrument POJO.
> 3. Re-load POJO.
> Is this correct?
1. JVM calls the classloader to find a class to run against
2. JBoss classloader takes the classname and calls classloader.getResource(classname.replace('.', '/'));
and gets a Stream to the actual bytecode of that class.
3. Javassist loads raw bytes into a javassist.CtClass object. Then we can do whatever the hell we want.
4. CtClass gets converted to an array of bytes
5. classloader.defineClass is called with the created array of bytes.
I guess the person above is asking this then:
If you have Javassist, why do you also need a custom classloader? Couldn't you do steps 1-5 without a custom classloader? What exactly does the custom classloader give you above and beyond the regular one, in helping you to implement aspects?
Is the classloader similar to the one(s) in JBoss 3? Is there a special AOP-centric classloader for JB4? JBoss 3 already has custom classloaders.
Even with Javassist, if you want to modify classes before their use in the JVM, you have to use a custom ClassLoader to intercept class loading.
Once a class is defined, it can be used in the JVM and cannot be changed (apart from class swaping with restrictions). That why you HAVE to intercept the load and make the modifications before the class is defined. And the only way to achieve this is to have a custom ClassLoader.
A regular ClassLoader only reads the class file and defines it. No way to instrument on the fly.
Please, look up and maybe compile and run attached sample.Test.java (sample program by Javassist), - I don't think that it uses custom class loader. Naturally, javassist.jar has to be in the classpath when the program is compiled and run. Let me know if this clarifies my questions.
> Please, look up and maybe compile and run attached
> sample.Test.java (sample program by Javassist), - I
> don't think that it uses custom class loader.
> Naturally, javassist.jar has to be in the classpath
> when the program is compiled and run. Let me know if
> this clarifies my questions.
Javassist does use a custom classloader. The problem with java.lang.ClassLoader is that the defineClass method is protected.
Search in the javassist.ClassPool class and you'll see that javassist uses a custom classloader.
So, regardless of this all, having to have a custom classloader causes an interesting side effect: POJO's are easy to apply aspects to, as long as their not in your WAR file, inside a servlet engine. This kind of makes AOP useless for a simple web application unfortunately.
Your AOP page says that work is being done to override Tomcat or Jetty's custom classloaders to resolve this issue. How is that work coming, any progress?