Is it possible to exclude fiel-sets in AspectJ pointcuts, so instrumentation does not stumble over final fields in Java 11?
When weaving the following aspect (the full example is here: https://github.com/DaGeRe/aspect-final-example):
@Pointcut("!within(de.aspectjtest..*)")
public void notWithinAspect() {
}
@Pointcut("!set(private * *)")
public void noSet() {
}
@Around("notWithinAspect() && noSet()")
public Object aroundStuff(final ProceedingJoinPoint thisJoinPoint, final EnclosingStaticPart thisEnclosingJoinPoint)
throws Throwable {
System.out.println("=== Call: " + thisJoinPoint.getSignature() + " " + thisJoinPoint.getKind());
System.out.println(thisJoinPoint.getSourceLocation() + " " + thisJoinPoint.getStaticPart());
System.out.println(thisJoinPoint.toLongString());
return thisJoinPoint.proceed();
}
into
class FinalFieldConstructorExample {
private final Integer parameters = 5;
public Integer getParameters() {
return parameters;
}
}
public class MainWithError {
public static void main(String[] args) {
FinalFieldConstructorExample example = new FinalFieldConstructorExample();
System.out.println(example.getParameters());
}
}
by java -cp target/test-0.1-SNAPSHOT.jar -javaagent:../aspect/target/aspectjtest-0.1-SNAPSHOT.jar de.test.MainWithError I get
Exception in thread "main" java.lang.IllegalAccessError: Update to non-static final field de.test.FinalFieldConstructorExample.parameters attempted from a different method (init$_aroundBody2) than the initialize
r method <init>
at de.test.FinalFieldConstructorExample.init$_aroundBody2(MainWithError.java:5)
at de.test.FinalFieldConstructorExample$AjcClosure3.run(MainWithError.java:1)
at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:167)
at de.aspectjtest.ExampleAspect.aroundStuff(ExampleAspect.java:27)
at de.test.FinalFieldConstructorExample.<init>(MainWithError.java:3)
at de.test.MainWithError.init$_aroundBody2(MainWithError.java:15)
at de.test.MainWithError$AjcClosure3.run(MainWithError.java:1)
at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:167)
at de.aspectjtest.ExampleAspect.aroundStuff(ExampleAspect.java:27)
at de.test.MainWithError.main_aroundBody10(MainWithError.java)
at de.test.MainWithError$AjcClosure11.run(MainWithError.java:1)
at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:167)
at de.aspectjtest.ExampleAspect.aroundStuff(ExampleAspect.java:27)
at de.test.MainWithError.main(MainWithError.java:15)
when I execute it with OpenJDK 11 (when setting everything to Java 8, it works fine). When removing the final modifier from FinalFieldConstructorExample and the && noSet() from the pointcut, it works fine and the output contains
=== Call: Integer java.lang.Integer.valueOf(int) method-call
MainWithoutError.java:5 call(Integer java.lang.Integer.valueOf(int))
call(public static java.lang.Integer java.lang.Integer.valueOf(int))
=== Call: Integer de.test.NonFinalFieldConstructorExample.parameters field-set
MainWithoutError.java:5 set(Integer de.test.NonFinalFieldConstructorExample.parameters)
set(private java.lang.Integer de.test.NonFinalFieldConstructorExample.parameters)
Therefore, I suppose the set-call (having a getKind of field-set, which seems not to be present in OpenJDK 8) to a static field is the reason of the problem. Is there any way of excluding it from AspectJ instrumentation (or working around the problem)? The documentation (https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html#primitive-pointcuts) states that get can be used in a Pointcut, but I did not find a way to specify final, and even if I add noSet, it seems to be somehow touched and the error appears.