Search code examples
javaaspectjjavacjavacompiler

Problem running AspectJ Load-Time-Weaving with java command


I am trying to run and test the aspectJ load time weaving. It compiled successfully.

javac -cp "lib/*" -d classes src/*.java

While running the program, the output is only Hello. Sadly, aspect did not run.

java -javaagent:lib/aspectjweaver-1.9.19.jar -cp "lib/*:classes/" Runner

This is my folder structure:

├── META-INF
│   └── aop.xml
├── classes
│   ├── HelloWorld.class
│   ├── HelloWorldAspect.class
│   └── Runner.class
├── lib
│   ├── aspectjrt-1.9.19.jar
│   └── aspectjweaver-1.9.19.jar
└── src
    ├── HelloWorld.java
    ├── HelloWorldAspect.java
    └── Runner.java

The file contents are:

public class HelloWorld {
  public void greet() {
    System.out.println("Hello");
  }
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;

@Aspect
public class HelloWorldAspect {
  @After("execution (* HelloWorld.*(..))")
  public void greetAspect() {
      System.out.println(", World");
  }
}
public class Runner {
  public static void main(String[] args) {
      HelloWorld h = new HelloWorld();
      h.greet();
  }
}
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver options="-verbose -showWeaveInfo">
        <include within="*" />
    </weaver>
</aspectj>

I tried -Daj.weaving.verbose=true to see if jar is loaded.

$ java -javaagent:lib/aspectjweaver-1.9.19.jar -cp "lib/*:classes/" -Dorg.aspectj.weaver.loadtime.configuration=/META-INF/aop.xml -Daj.weaving.verbose=true Runner

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.9.19 built on Wednesday Dec 21, 2022 at 06:57:22 PST
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info no configuration found. Disabling weaver for class loader sun.misc.Launcher$AppClassLoader@18b4aac2
Hello

I don't want to run the tool ajc and would like run with java program and run the aspect see the output Hello, World.


Solution

  • I did not try to compile and run your sample code yet, but I noticed two things when reading your question:

    1. Your aspect class is missing an @Aspect annotation.
    2. Your project is missing an aop.xml file, specifying the load-time weaving (LTW) options. This is why your console log says "no configuration found. Disabling weaver". See the AspectJ LTW documentation for more information.

    If these hints do not help you to solve your problem, feel free to comment on this answer, but please do try and study the documentation first.


    Update: After you posted the link to your reproducer on GitHub, still some open questions remain:

    How exactly did you build and run the project? Obviously, you did not use a build tool like Maven or Gradle. You committed a Vim swap file, so I can only guess that you somehow manually call Javac and Java from Vim via command line or so.

    Anyway, making another guess, the problem might be that the AspectJ weaver does not see the aop.xml file, because it should end up in classes/META-INF/aop.xml, which it does not. Normally, you should never commit class files or other generated files to Git, but in this case seeing your classes directory on GitHub gives me a clue.

    For example, when I tried to build your project in IntelliJ IDEA, aop.xml was not picked up, even after marking META-INF as a resource directory. Then I realised that I had to put META-INF into a subdirectory like resources and then mark resources as a resource directory. Only then, IDEA would copy the whole META-INF directory into the output directory, not just aop.xml.

    BTW, what is the MANIFEST.MF file with the strange duplicate Premain-Class entries good for? You do not need it at all for running the project. Just delete it.

    One more missing piece in this jigsaw puzzle is that you should add a list of active <aspects> to aop.xml:

    <aspectj>
      <weaver options="-verbose -showWeaveInfo">
        <include within="*"/>
      </weaver>
      <aspects>
        <aspect name="HelloWorldAspect"/>
      </aspects>
    </aspectj>
    

    This is also described on the manual page I linked to already.

    Besides, you should not put any classes or aspects into the default package. That only makes it difficult to use include/exclude configurations in the weaver, because you need to include the top level (empty package).