Community
Participate
Working Groups
When a <clinit> of a class contains after throwing advice that may catch ExceptionInInitializer errors due to an embedded advice aspectOf() that fails, the ExceptionInIntializer error does not get properly reported. For the example below: public class Main { static int x = 13; int y; public Main() { y= 14; } public static void main(String args[]) { Main m = new Main(); m.y = 3; System.out.println("hi"); } } aspect Aspect { before () : within(*) { System.out.println("BEFORE " + thisJoinPointStaticPart.getKind() + " at " + thisJoinPointStaticPart.getSourceLocation()); } after () : within(*) { System.out.println("AFTER " + thisJoinPointStaticPart.getKind() + " at " + thisJoinPointStaticPart.getSourceLocation()); } } .... when compiled with ajc, and then run, the following exception is given, Exception in thread "main" java.lang.NoClassDefFoundError at Main.<clinit>(Main.java:1) when really one wants the following: Exception in thread "main" java.lang.ExceptionInInitializerError at Main. ... Caused by: org.aspectj.lang.NoAspectBoundException: Aspect at Aspect.aspectOf .. ------------- Here is a fix ... I give the decompiled <clinit> for Main.java and indicate with comments, look for ***LJH ****, what can be woven to fix it. Basically, the catch block for after throwing, when in <clinit>, should first check if the caught exception if a ExceptionInInitializerError, and if so just throw it. ----------- static { org.aspectj.runtime.reflect.Factory r1; java.lang.Throwable r2, r31; int $i0; r1 = new Factory("Main.java", Class.forName("Main")); ajc$tjp_0 = r1.makeSJP("field-set", r1.makeFieldSig("8-x-Main-int-"), 2); ajc$tjp_1 = r1.makeSJP("staticinitialization", r1.makeInitializerSig("8--Main-"), 2); ajc$tjp_10 = r1.makeSJP("preinitialization", r1.makeConstructorSig("1--Main----"), 5); ajc$tjp_2 = r1.makeSJP("field-set", r1.makeFieldSig("0-y-Main-int-"), 6); ajc$tjp_3 = r1.makeSJP("constructor-execution", r1.makeConstructorSig("1--Main----"), 6); ajc$tjp_4 = r1.makeSJP("constructor-call", r1.makeConstructorSig("1--Main----"), 10); ajc$tjp_5 = r1.makeSJP("field-set", r1.makeFieldSig("0-y-Main-int-"), 11); ajc$tjp_6 = r1.makeSJP("field-get", r1.makeFieldSig("19-out-java.lang.System-java.io.PrintStream-"), 12); ajc$tjp_7 = r1.makeSJP("method-call", r1.makeMethodSig("1-println-java.io.PrintStream-java.lang.String:-arg0:--void-"), 12); ajc$tjp_8 = r1.makeSJP("method-execution", r1.makeMethodSig("9-main-Main-[Ljava.lang.String;:-args:--void-"), 10); ajc$tjp_9 = r1.makeSJP("initialization", r1.makeConstructorSig("1--Main----"), 6); try { Aspect.aspectOf().ajc$before$Aspect$1$36f01b1c(ajc$tjp_1); $i0 = 13; try { Aspect.aspectOf().ajc$before$Aspect$1$36f01b1c(ajc$tjp_0); x = $i0; } catch (Throwable $r30) { /*** LJH insert here *****/ if ($r30 instanceof ExceptionInIntializerError) //*** throw($r30); //*** /***********/ r31 = $r30; Aspect.aspectOf().ajc$after$Aspect$2$36f01b1c(ajc$tjp_0); throw r31; } Aspect.aspectOf().ajc$after$Aspect$2$36f01b1c(ajc$tjp_0); } catch (Throwable $r36) { /*** LJH insert here *****/ if ($r36 instanceof ExceptionInIntializerError) //*** throw($r36); //*** /***********/ r2 = $r36; Aspect.aspectOf().ajc$after$Aspect$2$36f01b1c(ajc$tjp_1); throw r2; } Aspect.aspectOf().ajc$after$Aspect$2$36f01b1c(ajc$tjp_1); }
marked as target 1.2.1
argh! bcel is a nightmare. It has taken me ages to program BCEL to generate: if ($r36 instanceof ExceptionInInitializerError) throw($r36); This is the final incantation for BCEL: if (this.getEnclosingMethod().getName().equals("<clinit>")) { ResolvedTypeX eiieType = world.resolve("java.lang.ExceptionInInitializerError"); ObjectType eiieBcelType = (ObjectType)BcelWorld.makeBcelType(eiieType); InstructionList ih = new InstructionList(InstructionConstants.NOP); handler.append(exceptionVar.createLoad(fact)); handler.append(fact.createInstanceOf(eiieBcelType)); BranchInstruction bi = InstructionFactory.createBranchInstruction( Constants.IFEQ,ih.getStart()); handler.append(bi); handler.append(exceptionVar.createLoad(fact)); handler.append(fact.createCheckCast(eiieBcelType)); handler.append(InstructionConstants.ATHROW); handler.append(ih); } I put that in the BcelShadow.weaveAfterThrowing() method. You can see it does a check to determine if it is in the <clinit> before generating this extra check. Here is the extra bytecode that appears in the method: 447: aload_1 448: instanceof #101; //class ExceptionInInitializerError 451: ifeq 459 454: aload_1 455: checkcast #101; //class ExceptionInInitializerError 458: athrow 459: nop Yes, there is one extra NOP but I don't want to fight with BCEL to remove it. I've put Lauries test program into the test suite to verify it behaves and we get the ExceptionInInitializerError rather than the NoClassDefFoundError. Thanks Laurie for describing the right fix :) fix checked in, waiting for build.
Fix available: BUILD COMPLETE - build.344 Date of build: 08/18/2004 11:27:31 Time to build: 92 minutes 31 seconds Last changed: 08/18/2004 10:55:59 Latest good AspectJ jar available at: download.eclipse.org/technology/ajdt/dev/aspectj-DEVELOPMENT.jar
Fix released as part of AspectJ 1.2.1