]> source.dussan.org Git - aspectj.git/commitdiff
389678: Better support for overweaving
authorAndy Clement <aclement@pivotal.io>
Mon, 21 Jan 2019 18:20:04 +0000 (10:20 -0800)
committerAndy Clement <aclement@pivotal.io>
Mon, 21 Jan 2019 18:20:04 +0000 (10:20 -0800)
More testcases for overweaving and better handling of WeaverStateInfo
to avoid the dreaded problems deserialized the 'special key' used
to store diffs.

With these changes once a class is woven via overweaving we switch
the diff we store in the weaverstateinfo to 0 byte array (indicating
overweaving happened for later weavers that see it). We also stop
writing the special 'key' into the attribute and avoid looking-for
and attempting to replace it at the end of weaving.

org.aspectj.matcher/src/org/aspectj/weaver/WeaverMessages.java
org.aspectj.matcher/src/org/aspectj/weaver/WeaverStateInfo.java
org.aspectj.matcher/src/org/aspectj/weaver/weaver-messages.properties
tests/src/org/aspectj/systemtest/ajc193/Ajc193Tests.java
tests/src/org/aspectj/systemtest/ajc193/ajc193.xml
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java

index 736220cd2ee955627ec11f499c6631e3b90e2ea4..5a64a77e8b2b423134fec7e3018a88db9cff566f 100644 (file)
@@ -1,18 +1,19 @@
 /*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004-2019 Contributors
  * All rights reserved. This program and the accompanying materials 
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.aspectj.weaver;
 
 import java.text.MessageFormat;
 import java.util.ResourceBundle;
 
+/**
+ * @author Andy Clement
+ * @author IBM
+ */
 public class WeaverMessages {
 
        private static ResourceBundle bundle = ResourceBundle.getBundle("org.aspectj.weaver.weaver-messages");
@@ -183,6 +184,8 @@ public class WeaverMessages {
 
        public static final String HAS_MEMBER_NOT_ENABLED = "hasMemberNotEnabled";
 
+       public static final String MUST_KEEP_OVERWEAVING_ONCE_START = "mustKeepOverweavingOnceStart";
+       
        // @AspectJ
        public static final String RETURNING_FORMAL_NOT_DECLARED_IN_ADVICE = "returningFormalNotDeclaredInAdvice";
        public static final String THROWN_FORMAL_NOT_DECLARED_IN_ADVICE = "thrownFormalNotDeclaredInAdvice";
index b9fc99da8e24aa34297aa4527adfe4419c455cc9..f0dcbf27028031ca2c3a9e86aa36fdd6f9bea4d0 100644 (file)
@@ -1,5 +1,5 @@
 /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * Copyright (c) 2002-2019 Palo Alto Research Center, Incorporated (PARC).
  * All rights reserved. 
  * This program and the accompanying materials are made available 
  * under the terms of the Eclipse Public License v1.0 
@@ -38,6 +38,8 @@ import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  * themselves If we are reweavable then we also have: Short: Number of aspects that touched this type in some way when it was
  * previously woven <String> The fully qualified name of each type Int: Length of class file data (i.e. the unwovenclassfile)
  * Byte[]: The class file data, compressed if REWEAVABLE_COMPRESSION_BIT set.
+ * 
+ * @author Andy Clement
  */
 public class WeaverStateInfo {
        private List<Entry> typeMungers;
@@ -230,6 +232,21 @@ public class WeaverStateInfo {
                }
        }
 
+       private final static byte[] NO_BYTES = new byte[0];
+       
+       /**
+        * If the weaver is ever invoked in over weaving mode, we should
+        * not include the key when writing out, it won't be replaced later.
+        * If we turn off the reweaving flag that unfortunately removes
+        * the 'what aspects have been woven into this type' list which we 
+        * want to keep as it helps overweaving avoid weaving an aspect in
+        * twice.
+        */
+       public void markOverweavingInUse() {
+               reweavableDiffMode = false;
+               unwovenClassFile = NO_BYTES;
+       }
+
        public void addConcreteMunger(ConcreteTypeMunger munger) {
                typeMungers.add(new Entry(munger.getAspectType(), munger.getMunger()));
        }
@@ -258,6 +275,10 @@ public class WeaverStateInfo {
                return oldStyle;
        }
 
+       public byte[] getUnwovenClassFileData() {
+               return unwovenClassFile;
+       }
+       
        public byte[] getUnwovenClassFileData(byte wovenClassFile[]) {
                if (unwovenClassFileIsADiff) {
                        unwovenClassFile = applyDiff(wovenClassFile, unwovenClassFile);
@@ -334,10 +355,12 @@ public class WeaverStateInfo {
                                }
                        } else {
                                classData = new byte[unwovenClassFileSize];
-                               int bytesread = s.read(classData);
-                               if (bytesread != unwovenClassFileSize) {
-                                       throw new IOException("ERROR whilst reading reweavable data, expected " + unwovenClassFileSize
-                                                       + " bytes, only found " + bytesread);
+                               if (unwovenClassFileSize != 0) {
+                                       int bytesread = s.read(classData);
+                                       if (bytesread != unwovenClassFileSize) {
+                                               throw new IOException("ERROR whilst reading reweavable data, expected " + unwovenClassFileSize
+                                                               + " bytes, only found " + bytesread);
+                                       }
                                }
                        }
 
index f47b3e38bc03ca9b67018ace7f32aa605ea33a18..2745ae9e7fbb6d329f6f4e0a535f5346083a58b7 100644 (file)
@@ -181,6 +181,7 @@ noParameterizedDeclaringTypesInCall=can't use parameterized type patterns for th
 noRawTypePointcutReferences=cannot use a raw type reference to refer to a pointcut in a generic type (use a parameterized reference instead)
 
 hasMemberNotEnabled=the type pattern {0} can only be used when the -XhasMember option is set
+mustKeepOverweavingOnceStart=the type {0} was previously subject to overweaving and after that can only be woven again in overweaving mode
 
 # Java5 features used in pre-Java 5 environment
 atannotationNeedsJava5=the @annotation pointcut expression is only supported at Java 5 compliance level or above
index 255d7d871e4f47c0105347dbae44a46f0e03eb14..801dd12f6ce33e98381498ca4cad421aed3859f9 100644 (file)
@@ -9,8 +9,10 @@ package org.aspectj.systemtest.ajc193;
 
 import java.io.File;
 
+import org.aspectj.apache.bcel.classfile.JavaClass;
 import org.aspectj.testing.XMLBasedAjcTestCase;
 import org.aspectj.testing.XMLBasedAjcTestCaseForJava10OrLater;
+import org.aspectj.weaver.WeaverStateInfo;
 
 import junit.framework.Test;
 
@@ -19,8 +21,72 @@ import junit.framework.Test;
  */
 public class Ajc193Tests extends XMLBasedAjcTestCaseForJava10OrLater {
 
+       public void testComplexOverweaving1() {
+               // This is the same code as the other test but overweaving OFF
+               runTest("overweaving");
+       }
+       
+       public void testComplexOverweaving2() throws Exception {
+               // This is the same code as the other test but overweaving ON
+               runTest("overweaving 2");
+               // Asserting the weaver state info in the tests that will drive overweaving behaviour:
+               
+               // After step 1 of the test, MyAspect will have been applied. 
+               JavaClass jc = getClassFrom(new File(ajc.getSandboxDirectory(),"ow1.jar"), "Application");
+               WeaverStateInfo wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertTrue(wsi.getUnwovenClassFileData().length>0);
+               
+               // After overweaving, MyAspect2 should also be getting applied but the unwovenclassfile
+               // data has been blanked out - because we can no longer use it, only overweaving is possible
+               // once one overweaving step is done
+               jc = getClassFrom(ajc.getSandboxDirectory(), "Application");
+               wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect2;, LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertEquals(0,wsi.getUnwovenClassFileData().length);
+       }
+       
+       // Two steps of overweaving
+       public void testComplexOverweaving3() throws Exception {
+               // This is the same code as the other test but overweaving ON
+               runTest("overweaving 3");
+               // Asserting the weaver state info in the tests that will drive overweaving behaviour:
+               
+               // After step 1 of the test, MyAspect will have been applied. 
+               JavaClass jc = getClassFrom(new File(ajc.getSandboxDirectory(),"ow1.jar"), "Application");
+               WeaverStateInfo wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertTrue(wsi.getUnwovenClassFileData().length>0);
+               
+               // After overweaving, MyAspect2 should also be getting applied but the unwovenclassfile
+               // data has been blanked out - because we can no longer use it, only overweaving is possible
+               // once one overweaving step is done
+               jc = getClassFrom(new File(ajc.getSandboxDirectory(),"ow3.jar"), "Application");
+               wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect2;, LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertEquals(0,wsi.getUnwovenClassFileData().length);
+
+               jc = getClassFrom(ajc.getSandboxDirectory(), "Application");
+               wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect3;, LMyAspect2;, LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertEquals(0,wsi.getUnwovenClassFileData().length);
+       }
+
+       // overweaving then attempt non overweaving - should fail
+       public void testComplexOverweaving4() throws Exception {
+               // This is the same code as the other test but overweaving ON
+               runTest("overweaving 4");
+               // Asserting the weaver state info in the tests that will drive overweaving behaviour:
+               
+               // After step 1 of the test, MyAspect will have been applied. 
+               JavaClass jc = getClassFrom(new File(ajc.getSandboxDirectory(),"ow1.jar"), "Application");
+               WeaverStateInfo wsi = getWeaverStateInfo(jc);
+               assertEquals("[LMyAspect;]", wsi.getAspectsAffectingType().toString());
+               assertTrue(wsi.getUnwovenClassFileData().length>0);             
+       }
+       
        // Altered version of this test from org.aspectj.systemtest.ajc150.Enums for 542682
-       public void decpOnEnumNotAllowed_xlints() {
+       public void testDecpOnEnumNotAllowed_xlints() {
                runTest("wildcard enum match in itd");
        }
 
index d5ed0f1c1fa131a468302628e8a128fcf17de857..f391c50d7e04a9887f2d5d45665f5160db81ec77 100644 (file)
@@ -2,6 +2,124 @@
 
 <suite>
 
+    <ajc-test dir="bugs193/389678" vm="1.8" title="overweaving">
+        <compile files="OverWeave_1/src/Application.java,OverWeave_1/src/MyAspect.aj" options="-showWeaveInfo -1.8" outjar="ow1.jar">
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+        </compile>
+        <compile files="OverWeave_2/src/MyAspect2.aj" options="-1.8" outjar="ow2.jar">
+               <message kind="warning" text="advice defined in MyAspect2 has not been applied"/>
+        </compile>
+        <compile inpath="ow1.jar" aspectpath="ow2.jar" options="-1.8 -showWeaveInfo">
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (ow1.jar!MyAspect.class:2(from MyAspect.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (ow1.jar!MyAspect.class:2(from MyAspect.aj))"/>
+        </compile>
+        <run class="Application" classpath="ow2.jar">
+               <stdout>
+               <line text="MyAspect -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect2 -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect -> execution(void Application.sayHelloTo(String))"/>
+               <line text="MyAspect2 -> execution(void Application.sayHelloTo(String))"/>
+               <line text="Hello world!"/>
+               </stdout>
+        </run>
+    </ajc-test>
+
+    <ajc-test dir="bugs193/389678" vm="1.8" title="overweaving 2">
+        <compile files="OverWeave_1/src/Application.java,OverWeave_1/src/MyAspect.aj" options="-showWeaveInfo -1.8" outjar="ow1.jar">
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+        </compile>
+        <compile files="OverWeave_2/src/MyAspect2.aj" options="-1.8" outjar="ow2.jar">
+               <message kind="warning" text="advice defined in MyAspect2 has not been applied"/>
+        </compile>
+        <compile inpath="ow1.jar" aspectpath="ow2.jar" options="-showWeaveInfo -1.8 -Xset:overWeaving=true">
+               <!-- this is a bit unfortunate, basically MyAspect is not being re-applied because of overweaving
+                    so we get a message that it hasn't been applied. But really it doesn't need to be. -->
+               <message kind="warning" text="advice defined in MyAspect has not been applied"/>
+<!-- These two don't come out because we are using overweaving to apply MyAspect2 where MyAspect is already applied.
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (ow1.jar!MyAspect.class:2(from MyAspect.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (ow1.jar!MyAspect.class:2(from MyAspect.aj))"/>
+-->
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+        </compile>
+        <run class="Application" classpath="ow2.jar">
+               <stdout>
+               <!--  notice order change to overweaving usage -->
+               <line text="MyAspect2 -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect2 -> execution(void Application.sayHelloTo(String))"/>
+               <line text="MyAspect -> execution(void Application.sayHelloTo(String))"/>
+               <line text="Hello world!"/>
+               </stdout>
+        </run>
+    </ajc-test>
+    
+    <ajc-test dir="bugs193/389678" vm="1.8" title="overweaving 3">
+        <compile files="OverWeave_1/src/Application.java,OverWeave_1/src/MyAspect.aj" options="-showWeaveInfo -1.8" outjar="ow1.jar">
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+        </compile>
+        <compile files="OverWeave_2/src/MyAspect2.aj" options="-1.8" outjar="ow2.jar">
+               <message kind="warning" text="advice defined in MyAspect2 has not been applied"/>
+        </compile>
+        <compile files="OverWeave_4/src/MyAspect3.aj" options="-1.8" outjar="ow4.jar">
+               <message kind="warning" text="advice defined in MyAspect3 has not been applied"/>
+        </compile>
+        <compile inpath="ow1.jar" aspectpath="ow2.jar" options="-showWeaveInfo -1.8 -Xset:overWeaving=true" outjar="ow3.jar">
+               <!-- this is a bit unfortunate, basically MyAspect is not being re-applied because of overweaving
+                    so we get a message that it hasn't been applied. But really it doesn't need to be. -->
+               <message kind="warning" text="advice defined in MyAspect has not been applied"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+        </compile>
+         <compile inpath="ow3.jar" aspectpath="ow4.jar" options="-showWeaveInfo -1.8 -Xset:overWeaving=true">
+               <!-- this is a bit unfortunate, basically MyAspect is not being re-applied because of overweaving
+                    so we get a message that it hasn't been applied. But really it doesn't need to be. -->
+               <message kind="warning" text="advice defined in MyAspect has not been applied"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect3' (ow4.jar!MyAspect3.class:2(from MyAspect3.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect3' (ow4.jar!MyAspect3.class:2(from MyAspect3.aj))"/>
+        </compile>
+        <run class="Application" classpath="ow2.jar">
+               <stdout>
+               <line text="MyAspect3 -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect2 -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect -> execution(void Application.main(String[]))"/>
+               <line text="MyAspect3 -> execution(void Application.sayHelloTo(String))"/>
+               <line text="MyAspect2 -> execution(void Application.sayHelloTo(String))"/>
+               <line text="MyAspect -> execution(void Application.sayHelloTo(String))"/>
+               <line text="Hello world!"/>
+               </stdout>
+        </run>
+    </ajc-test>
+    
+    <ajc-test dir="bugs193/389678" vm="1.8" title="overweaving 4">
+        <compile files="OverWeave_1/src/Application.java,OverWeave_1/src/MyAspect.aj" options="-showWeaveInfo -1.8" outjar="ow1.jar">
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect' (MyAspect.aj:2)"/>
+        </compile>
+        <compile files="OverWeave_2/src/MyAspect2.aj" options="-1.8" outjar="ow2.jar">
+               <message kind="warning" text="advice defined in MyAspect2 has not been applied"/>
+        </compile>
+        <compile files="OverWeave_4/src/MyAspect3.aj" options="-1.8" outjar="ow4.jar">
+               <message kind="warning" text="advice defined in MyAspect3 has not been applied"/>
+        </compile>
+        <compile inpath="ow1.jar" aspectpath="ow2.jar" options="-showWeaveInfo -1.8 -Xset:overWeaving=true" outjar="ow3.jar">
+               <!-- this is a bit unfortunate, basically MyAspect is not being re-applied because of overweaving
+                    so we get a message that it hasn't been applied. But really it doesn't need to be. -->
+               <message kind="warning" text="advice defined in MyAspect has not been applied"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.main(java.lang.String[]))' in Type 'Application' (Application.java:2) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+               <message kind="weave" text="Join point 'method-execution(void Application.sayHelloTo(java.lang.String))' in Type 'Application' (Application.java:6) advised by before advice from 'MyAspect2' (ow2.jar!MyAspect2.class:2(from MyAspect2.aj))"/>
+        </compile>
+         <compile inpath="ow3.jar" aspectpath="ow4.jar:ow2.jar" options="-1.8">
+               <message kind="error" text="the type Application was previously subject to overweaving and after that can only be woven again in overweaving mode"/>
+               <message kind="error" text="the type MyAspect was previously subject to overweaving and after that can only be woven again in overweaving mode"/>
+        </compile>
+    </ajc-test>
+    
     <ajc-test dir="bugs193/542682" vm="1.5" title="wildcard enum match in itd">
         <compile files="SimpleEnum.java,SimpleEnum2.java,EnumAspect04.aj" options="-1.5">
             <message kind="warning" line="8" text="enum type SimpleEnum2 matches a declare parents type pattern but is being ignored"/>
index b4eaa3dd4eb381157a87fae6dc7906f2661ca11a..83919ed5022a7242a77f9a2421864fc6ec21d764 100644 (file)
@@ -538,8 +538,12 @@ class BcelClassWeaver implements IClassWeaver {
                if (inReweavableMode) {
                        WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo(true);
                        wsi.addAspectsAffectingType(aspectsAffectingType);
-                       wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes());
-                       wsi.setReweavable(true);
+                       if (!world.isOverWeaving()) {
+                               wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes());
+                               wsi.setReweavable(true);
+                       } else {
+                               wsi.markOverweavingInUse();
+                       }
                } else {
                        clazz.getOrCreateWeaverStateInfo(false).setReweavable(false);
                }
index 4306602e7832300c41a7f4ff2dc00af2b293f1fd..f83a7937987aeb6dd80ae316d172fc7be3bfec59 100644 (file)
@@ -1364,15 +1364,12 @@ public class BcelWeaver {
                                if (!alreadyConfirmedReweavableState.contains(requiredTypeSignature)) {
                                        ResolvedType rtx = world.resolve(UnresolvedType.forSignature(requiredTypeSignature), true);
                                        boolean exists = !rtx.isMissing();
-                                       if (!exists) {
-                                               world.getLint().missingAspectForReweaving.signal(new String[] { rtx.getName(), className },
+                                       if (!world.isOverWeaving()) {
+                                               if (!exists) {
+                                                       world.getLint().missingAspectForReweaving.signal(new String[] { rtx.getName(), className },
                                                                classType.getSourceLocation(), null);
-                                               // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.MISSING_REWEAVABLE_TYPE,
-                                               // requiredTypeName, className), classType.getSourceLocation(), null);
-                                       } else {
-                                               if (world.isOverWeaving()) {
-                                                       // System.out.println(">> Removing " + requiredTypeName + " from weaving process: "
-                                                       // + xcutSet.deleteAspect(rtx));
+                                                       // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.MISSING_REWEAVABLE_TYPE,
+                                                       // requiredTypeName, className), classType.getSourceLocation(), null);
                                                } else {
                                                        // weaved in aspect that are not declared in aop.xml
                                                        // trigger an error for now
@@ -1386,8 +1383,8 @@ public class BcelWeaver {
                                                                world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.VERIFIED_REWEAVABLE_TYPE,
                                                                                rtx.getName(), rtx.getSourceLocation().getSourceFile()), null, null);
                                                        }
+                                                       alreadyConfirmedReweavableState.add(requiredTypeSignature);
                                                }
-                                               alreadyConfirmedReweavableState.add(requiredTypeSignature);
                                        }
                                }
                        }
@@ -1396,11 +1393,21 @@ public class BcelWeaver {
                        // ().getFileName(), wsi.getUnwovenClassFileData()));
                        // new: reweavable default with clever diff
                        if (!world.isOverWeaving()) {
-                               byte[] bytes = wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes());
-                               WeaverVersionInfo wvi = classType.getWeaverVersionAttribute();
-                               JavaClass newJavaClass = Utility.makeJavaClass(classType.getJavaClass().getFileName(), bytes);
-                               classType.setJavaClass(newJavaClass, true);
-                               classType.getResolvedTypeX().ensureConsistent();
+                               byte[] ucfd = wsi.getUnwovenClassFileData();
+                               if (ucfd.length == 0) {
+                                       // Size 0 indicates the class was previously overwoven, so you need to be overweaving now!
+                                       world.getMessageHandler().handleMessage(
+                                                       MessageUtil.error(
+                                                       WeaverMessages.format(WeaverMessages.MUST_KEEP_OVERWEAVING_ONCE_START,
+                                                                       className)));
+//                                                                     onType.getName(), annoX.getTypeName(), annoX.getValidTargets()),
+//                                                     decA.getSourceLocation()));                                     
+                               } else {
+                                       byte[] bytes = wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes());
+                                       JavaClass newJavaClass = Utility.makeJavaClass(classType.getJavaClass().getFileName(), bytes);
+                                       classType.setJavaClass(newJavaClass, true);
+                                       classType.getResolvedTypeX().ensureConsistent();
+                               }
                        }
                        // } else {
                        // classType.resetState();
index 95ef524b5fd3f14fb79dbf9c4fa5f93345d9df58..83189e1d4c4818be86d9e00c4ba79359986b4485 100644 (file)
@@ -533,9 +533,14 @@ public final class LazyClassGen {
                        myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(), getConstantPool()));
                }
 
-               // 352389: don't add another one (there will already be one there and this new one won't deserialize correctly)
-               if (!world.isOverWeaving() || !myGen.hasAttribute(WeaverState.AttributeName)) {
-                       if (myType != null && myType.getWeaverState() != null) {
+               // see 389678: TODO more finessing possible here?
+               if (world.isOverWeaving()) {
+                       if (myGen.hasAttribute(WeaverState.AttributeName) && myType!=null && myType.getWeaverState() != null) {
+                               myGen.removeAttribute(myGen.getAttribute(WeaverState.AttributeName));
+                               myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
+                       }
+               } else {
+                       if (!myGen.hasAttribute(WeaverState.AttributeName) && myType != null && myType.getWeaverState() != null) {
                                myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
                        }
                }
@@ -750,8 +755,8 @@ public final class LazyClassGen {
        public byte[] getJavaClassBytesIncludingReweavable(BcelWorld world) {
                writeBack(world);
                byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
-               // At 1.6 stackmaps are optional
-               // At 1.7 or later stackmaps are required (if not turning off the verifier)
+               // At 1.6 stackmaps are optional, whilst at 1.7 and later they
+               // are required (unless turning off the verifier)
                if ((myGen.getMajor() == Constants.MAJOR_1_6 && world.shouldGenerateStackMaps()) || myGen.getMajor() > Constants.MAJOR_1_6) {
                        if (!AsmDetector.isAsmAround) {
                                throw new BCException("Unable to find Asm for stackmap generation (Looking for 'aj.org.objectweb.asm.ClassReader'). Stackmap generation for woven code is required to avoid verify errors on a Java 1.7 or higher runtime");
@@ -760,7 +765,7 @@ public final class LazyClassGen {
                }
 
                WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
-               if (wsi != null && wsi.isReweavable()) { // && !reweavableDataInserted
+               if (wsi != null && wsi.isReweavable() && !world.isOverWeaving()) { // && !reweavableDataInserted
                        // reweavableDataInserted = true;
                        return wsi.replaceKeyWithDiff(wovenClassFileData);
                } else {