javaclasspathclassloaderaspectjaspectj-maven-plugin

aspecj-maven-plugin, weaving dependency feature, random load java class


I use maven-aspectj-plugin in a multi modules project using maven as a dependency tool. A simple demo project, you could find here demo-project.

At my real project, for the compatibiliy with lombok, I use an unusually dependency graph of modules;

starter ---> ajc ----> my business modules.

The starter is the program entrancem. The aspects are in ajc module which has only aspects. All the java class which will be weaved into are in business modules. Using this dependency, so I could use lombok in my business modules, and the weaving process appears in the compile of ajc module. At that time, the business module has been compiled to byte code with lombok. Of course, I need use the weaveDependency style.

It has been working well for a long time. But today I begin my another project. The proceeding point was not enter into. The most interesting part is the aspect work well when i use idea to run the application. But I deploy it with jars. The program do not enter aspect. I try to reproduce the bug using a simple project demo. But the aspect works well unexpectedly.

So I dig into target directory of ajc module. I found the class files which are same with the weaving goal java class in my bussiness modules. Interesting, it answer my another question. The weaving dependency feature didn't edit the target jar. How it works? Now, I know that, it add a new class with aspect in aspects directory. Jvm may choose one of java classes.

Windows Explorer, showing identically named class files in two different directories

I think my questions should comes from this random procedure.

And the finally questions: If my guess is right. The weave dependency featue is that copy the original java class and edit it, then put it in a another directory or another jar, but shares same package name and class name with the orignal java class. But it will bring another problem, there are two java class file with same package name and same class name. The class loading will perform different in different OS thanks to file inode and it dependend on the os file system.

Are there any mechanisms to prevent class loader random load one java class file of these two.

I have give my guess in the details. Want to hear explain from plugin author about this question


Solution

  • Instead of thinking classpath ordering, you should use the clean and obvious choice to not include the original JARs woven by your aspects in the classpath (or the fat JAR) at all, because everything on AspectJ's inpath during compilation (weaveDependencies in AspectJ Maven) will be in the compilation result of the corresponding module, without regard if particular classes have been affected by aspects or not. Your other modules ought to depend on the woven modules, but not on their transitive unwoven dependencies.

    How to achieve that, strongly depends on your situation. Some options include

    All of the above can help in Maven, depending on your situation, which is why I asked detail questions that you are unwilling to answer more clearly. Not my problem, you are shooting yourself into your own foot.

    If you get it working in Maven, but somehow not in your IDE, because the IDE maybe does not understand what Flatten Maven does and still adds the weave dependencies on the classpath in a single multi-module project, you might have to use a separate project for Aspect weaving and creating an uber JAR or a module with dependency-reduced POM, mvn install it and then consume it in project B. But usually there are ways to avoid that, even though it is a clean and simple way, too.

    Here is a PR for your project, showing how to adjust Maven Dependency Plugin to copy the correct dependencies to the lib directory. If you run starter with that lib directory on the classpath or put the two into a fat JAR together, it should work. No more duplicate classes on the classpath.