0

I'm creating simple experimental program, which use LTW to weave aspect into a class, however aspect load-time weaving doesn't happening. You can check and use code, which I will describe later, in GitHub. I'm using Java 17 and IntelliJ IDE.

Used aspect:


@Aspect
@Component
public class MonitoringAspect {

    @Pointcut("execution(* com.sj.utilities.Watch.*(..))")
    public void monitoringOperation(){}

    @Around("monitoringOperation()")
    public Object aroundAdvice(ProceedingJoinPoint pjp)
            throws Throwable {
        System.out.println("Before " + pjp.getSignature() + " execution!");

        long startTime = System.nanoTime();
        Object retVal = pjp.proceed();
        long endTime = System.nanoTime();
        long executingTime = endTime - startTime;
        System.out.println("Method's execution time:\n"
                + "\t" + executingTime + " ns\n"
                + "\t" + (executingTime / 1000) + " μs\n"
                + "\t" + (executingTime / 1000000) + " ms\n"
                + "\t" + (executingTime / 1000000000) + " s");
        System.out.println("After " + pjp.getSignature() + " execution!");

        return retVal;
    }

}

I tried to remove @Component, because aspect bean is not required, however it changed nothing.

Advised by aspect is simple method sleeping of Watch class, with implementation of FictiveWatch interface (Interface exists only for Spring to use JDK dynamic proxies).

Created Java annotation config:

@Configuration
//@EnableAspectJAutoProxy
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
@ComponentScan("com.sj")
public class AOPConfig implements LoadTimeWeavingConfigurer {

    @Override
    public LoadTimeWeaver getLoadTimeWeaver() {
        return new InstrumentationLoadTimeWeaver();
    }

    @Bean
    public InstrumentationLoadTimeWeaver loadTimeWeaver()  throws Throwable {
        return new InstrumentationLoadTimeWeaver();
    }

}

As well as xml config:

<?xml version="1.0" encoding="UTF-8"?>
<beans <!-- namespaces ...-->

    <!-- this switches on the load-time weaving -->
    <context:load-time-weaver
        weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

    <!-- this switches on the spring aop autoproxy -->
    <!--<aop:aspectj-autoproxy/>-->

    <!-- a service object; we will be profiling its methods -->
    <bean id="watch"
          class="com.sj.utilities.Watch"/>
    <bean id="monitoringAspect"
          class="com.sj.aspects.MonitoringAspect"/>

</beans>

To use weave aspect I use this META-INF/aop.xml file:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver
            options="-verbose -showWeaveInfo">
        <!-- only weave classes in our application-specific packages -->
        <include within="com.sj..*"/>
    </weaver>
    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="com.sj.aspects.MonitoringAspect"/>
    </aspects>
</aspectj>

Driver class:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        //Check used JVM arguments
        System.out.println(ManagementFactory.getRuntimeMXBean().getInputArguments());

        //Java class LTW config
        //ApplicationContext context = new AnnotationConfigApplicationContext(AOPConfig.class);

        //XML LTW config
        ApplicationContext context = new ClassPathXmlApplicationContext("config/aop-xml-conf.xml");
        Watch watch = context.getBean(Watch.class);
        watch.sleeping(3000);
    }
}

In the driver class, I use AnnotationConfig or XMLConfig to use LTW, but weaving isn't happening, so crosscutting functionality isn't applied. As well as I print used by JVM arguments.

The only thing I see, when using AnnotationConfig or XMLConfig, is JVM arguments that I use:

[--add-opens=java.base/java.lang=ALL-UNNAMED, -Dspring.aop.proxy-target-class=false, -Dorg.aspectj.weaver.loadtime.configuration=trace, -Dorg.aspectj.weaver.loadtime.verbose=true, -javaagent:E:\intelliJIdea_dir\IntelliJ IDEA Community Edition 2022.2.1\lib\idea_rt.jar=55606:E:\intelliJIdea_dir\IntelliJ IDEA Community Edition 2022.2.1\bin, -Dfile.encoding=UTF-8]

As well as result of Watch class sleeping method:

Slept 3000 ms

Why weaving is not happening, which part of written code is not right? As per Spring documentation on LTW, as well as other answers on questions for LTW topic everything should be alright, or I'm missing something?

  • Did you forget to add `-javaagent:/path/to/aspectjweaver-1.9.19.jar` or similar? – kriegaex Feb 24 '23 at 13:33
  • Nothing changes if I add it. As well as isn't it already used through IntelliJ -javaagent? (Well, aspectjweaver is specified in -classpath, but IntelliJ idea_rt.jar in -javaagent) – Sergejs Jevstigņejevs Feb 24 '23 at 14:00
  • The IntelliJ javaagent is completely unrelated to AspectJ, you really do need the AspectJ weaver on the JVM command line as a Java agent, not just on the classpath. – kriegaex Feb 25 '23 at 07:33

1 Answers1

0

Did you accidentally add the -javaagent option to the program arguments instead of VM arguments? For me, your project works nicely.

IntelliJ IDEA: select VM options

IntelliJ IDEA: show added VM options

Running the program yields:

[AppClassLoader@1d44bcfa] info AspectJ Weaver Version 1.9.19 built on Wednesday Dec 21, 2022 at 06:57:22 PST
[AppClassLoader@1d44bcfa] info register classloader jdk.internal.loader.ClassLoaders$AppClassLoader@1d44bcfa
[AppClassLoader@1d44bcfa] info using configuration .../target/classes/META-INF/aop.xml
[AppClassLoader@1d44bcfa] info register aspect com.sj.aspects.MonitoringAspect
[--add-opens=java.base/java.lang=ALL-UNNAMED, -javaagent:src/main/resources/aspectjweaver-1.9.19.jar, -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=56248:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\bin, -Dfile.encoding=UTF-8]
...
[AppClassLoader@1d44bcfa] weaveinfo Join point 'method-execution(void com.sj.utilities.Watch.sleeping(long))' in Type 'com.sj.utilities.Watch' (Watch.java:9) advised by around advice from 'com.sj.aspects.MonitoringAspect' (MonitoringAspect.java)
Before void com.sj.utilities.Watch.sleeping(long) execution!
Slept 3000 ms
Method's execution time:
    3010467900 ns
    3010467 μs
    3010 ms
    3 s
After void com.sj.utilities.Watch.sleeping(long) execution!
kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Well, no, I added it to JVM arguments. But in the end the culprit is this JVM argument: ```-Dorg.aspectj.weaver.loadtime.configuration=trace ```. It prevented crosscutting functionality from working. – Sergejs Jevstigņejevs Feb 25 '23 at 11:52
  • OMG, why would you use an exotic setting and not even mention it? Can you not start simple instead of complicated? I feel like I wasted a lot of time, cloning your project, trying to reproduce your problem, writing here and making extra screenshots for you. Please learn how to ask questions. – kriegaex Feb 25 '23 at 16:00