When trying to apply LTW to DataSource classes on WildFly application server, we see that sometimes weaving silently fails. The two "ingredients" for this to happen appear to be:
More than one datasource of the same driver exists, and
Using an Around advice on DataSource method
Enabling debugging and weaveInfo shows that the advice is applied, yet the actual advice code does not run, as if weaving did not occur.
After some digging, the root cause appears to be as follows:
WildFly is using jboss-modules class loading system, which loads classes using org.jboss.modules.ModuleClassLoader class.
ModuleClassLoader does not lock anything while loading classes. It could very well call defineClass() to load the same class into the same class loader in two threads in parallel. Obviously one of the calls would fail in that case, but it recovers from this.
With two DataSource instances present, WildFly sets them up in two executor jobs that can run in parallel on different threads, hence causing defineClass() to be called on the DataSource class twice in parallel.
While defineClass() runs, AspectJ LTW agent is invoked to retransform the loaded class - so in our case it's invoked twice in parallel on the same weaver instance.
Usually, AspectJ has no problem weaving the class "twice", meaning that in each weaving operation AspectJ is receiving the original class bytes and is returning the modified class bytes, and it doesn't care how many times it happens or what happens in other threads.
However, with Around advice, an inner class is being created. AspectJ would not want to create the inner class twice.
So AspectJ has a mechanism to guard against weaving a class with an associated generated class twice on the same weaver.
The bug is that when such a "collision" is detected, AspectJ avoids weaving again (to avoid creating the generated class), but is returning the original class bytes and not the woven bytes.
Because all this is running in parallel in two threads, sometimes the thread that got to weave the class second (and therefore is seeing not-woven class) makes it first to installing the class in the ClassLoader, and so this un-woven class "wins".
Tested on versions 29 and 30 with several Java-17 distributions on Linux.
When trying to apply LTW to DataSource classes on WildFly application server, we see that sometimes weaving silently fails. The two "ingredients" for this to happen appear to be:
Enabling debugging and weaveInfo shows that the advice is applied, yet the actual advice code does not run, as if weaving did not occur.
After some digging, the root cause appears to be as follows:
Tested on versions 29 and 30 with several Java-17 distributions on Linux.
A reproducer project with a mock class loader can be found here: https://gitlab.com/urisimchoni/aspectj-parallel-issue