Community
Participate
Working Groups
Seems like the verifier in Java 9 became more strict. AJC generates code that attempts to initialize static final fields in ajc$preClinit, which is caleed on <clinit>, e.g., //regular field private static final String ADDRESS; //inserted by ajc private static final /* synthetic */ JoinPoint.StaticPart ajc$tjp_0; static { //post-weaved code ServiceImpl.ajc$preClinit(); ADDRESS = "https://..."; } private static synthetic void ajc$preClinit() { Factory factory = new Factory("ServiceImpl.java", ServiceImpl.class); ajc$tjp_0 = factory.makeSJP("method-execution", (Signature)factory.makeMethodSig("80", "remove", "le.package.ServiceImpl", "[Ljava.lang.String;", "names", "", "void"), 1344); } Seems like Java 9 doesn't like this and it throws an IllegalAccessError during classloading: ServiceImpl.ajc$tjp_0 attempted from a different method (ajc$preClinit) than the initializer method <clinit> I believe the only definitive solution, apart from removing the final modifier from ajc generated fields, would be inlining ajc$preClinit. Tested with aspectj 1.9.0.BETA-5 (from http://repo.spring.io/milestone) and JDK build 9-ea+164.
Anyone awaiting for this fix, can work-around by patching aspectjtools.jar with a trivial change in org.aspectj.weaver.bcel.LazyClassGen public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) { Field tjpField = tjpFields.get(shadow); if (tjpField != null) { return tjpField; } int modifiers = Modifier.STATIC /*| Modifier.FINAL*/ ; ... }
Another similar issue when ajc compiles aspects themselves. AJC produces ajc$perSingletonInstance as static final field and ajc$postClinit attempts to initialize it. Quick Hack: Patch org.aspectj.weaver.AjcMemberMaker public static ResolvedMember perSingletonField(UnresolvedType declaringType) { return new ResolvedMemberImpl(Member.FIELD, declaringType, PUBLIC_STATIC, NameMangler.PERSINGLETON_FIELD_NAME, declaringType.getSignature()); }
Fixed up (well mostly). Removed the final modifier. Unfortunately that doesn't help the case of weaving default methods in an interface since you can't take the final off in that case (and the preclinit will need inlining). But I think that is a much smaller issue than the general problem. So will capture it separately (address it when someone starts hitting it).