]> source.dussan.org Git - aspectj.git/commitdiff
533038: Clear some generated class entries during class redefinition
authorAndy Clement <aclement@pivotal.io>
Mon, 2 Apr 2018 17:15:20 +0000 (10:15 -0700)
committerAndy Clement <aclement@pivotal.io>
Mon, 2 Apr 2018 17:15:20 +0000 (10:15 -0700)
loadtime/src/org/aspectj/weaver/loadtime/Aj.java
loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java
loadtime5/java5-src/org/aspectj/weaver/loadtime/ClassPreProcessorAgentAdapter.java

index 0654e4cba920647bd1e7e95d28e16ae117a78ffa..e9c347acbd8188d97631d53294bbe81684489865 100644 (file)
@@ -66,6 +66,7 @@ public class Aj implements ClassPreProcessor {
        /**
         * Initialization
         */
+       @Override
        public void initialize() {
 
        }
@@ -80,6 +81,7 @@ public class Aj implements ClassPreProcessor {
         * @param loader
         * @return woven bytes
         */
+       @Override
        public byte[] preProcess(String className, byte[] bytes, ClassLoader loader, ProtectionDomain protectionDomain) {
                // TODO AV needs to doc that
                if (loader == null || className == null || loader.getClass().getName().equals(deleLoader)) {
@@ -171,6 +173,7 @@ public class Aj implements ClassPreProcessor {
                        return instance;
                }
 
+               @Override
                public boolean equals(Object obj) {
                        if (!(obj instanceof AdaptorKey)) {
                                return false;
@@ -181,6 +184,7 @@ public class Aj implements ClassPreProcessor {
                                        && loaderClass.equals(other.loaderClass);
                }
 
+               @Override
                public int hashCode() {
                        return hashValue;
                }
@@ -301,7 +305,7 @@ public class Aj implements ClassPreProcessor {
                 if (loader.equals(myClassLoader)){
                     adaptor = myClassLoaderAdaptor;
                 } else {
-                       adaptor = (ExplicitlyInitializedClassLoaderWeavingAdaptor) weavingAdaptors.get(adaptorKey);
+                       adaptor = weavingAdaptors.get(adaptorKey);
                 }
                                if (adaptor == null) {
                                        // create it and put it back in the weavingAdaptors map but avoid any kind of instantiation
@@ -370,4 +374,9 @@ public class Aj implements ClassPreProcessor {
                ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses();
        }
 
+       @Override
+       public void prepareForRedefinition(ClassLoader loader, String className) {
+               ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClassesFor(className);
+       }
+
 }
\ No newline at end of file
index 24c5ba1bd7d558198786ee95a56d52b4c7261f16..6fa259d03d6b64a8d0138fd4e2e7380fdf6b5089 100644 (file)
@@ -12,8 +12,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.ProtectionDomain;
@@ -24,6 +22,8 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -114,6 +114,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
         * 
         * @deprecated
         */
+       @Deprecated
        public ClassLoaderWeavingAdaptor(final ClassLoader deprecatedLoader, final IWeavingContext deprecatedContext) {
                super();
                if (trace.isTraceEnabled()) {
@@ -135,6 +136,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
                 * Callback when we need to define a Closure in the JVM
                 * 
                 */
+               @Override
                public void acceptClass (String name, byte[] originalBytes, byte[] wovenBytes) {
                        try {
                                if (shouldDump(name.replace('/', '.'), false)) {
@@ -1006,6 +1008,30 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
                generatedClasses = new HashMap<String, IUnwovenClassFile>();
        }
 
+       /**
+        * Remove generated classes based on the supplied className. This will
+        * remove any entries related to this name - so the class itself plus
+        * and inner classes.
+        * @param className a slashed classname (e.g. com/foo/Bar)
+        */
+       public void flushGeneratedClassesFor(String className) {
+               try {
+                       String dottedClassName = className.replace('/', '.');
+                       String dottedClassNameDollar = dottedClassName+"$"; // to pickup inner classes
+                       Iterator<Map.Entry<String, IUnwovenClassFile>> iter = generatedClasses.entrySet().iterator();
+                       while (iter.hasNext()) {
+                               Entry<String, IUnwovenClassFile> next = iter.next();
+                               String existingGeneratedName = next.getKey();
+                               if (existingGeneratedName.equals(dottedClassName) ||
+                                               existingGeneratedName.startsWith(dottedClassNameDollar)) {
+                                       iter.remove();
+                               }
+                       }
+               } catch (Throwable t) {
+                       new RuntimeException("Unexpected problem tidying up generated classes for "+className,t).printStackTrace();
+               }
+       }
+
        private Unsafe unsafe;
 
        private Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
@@ -1061,4 +1087,5 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
                        trace.exit("defineClass", clazz);
                }
        }
+
 }
\ No newline at end of file
index 12e6202152bfc4e7511a0472134eed0c2ac2e281..97348b281faf5d6d433eb1e8f4256f34964c31fe 100644 (file)
@@ -1,13 +1,10 @@
 /*******************************************************************************
- * Copyright (c) 2005 Contributors.
+ * Copyright (c) 2005,2018 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://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Alexandre Vasseur         initial implementation
  *******************************************************************************/
 package org.aspectj.weaver.loadtime;
 
@@ -18,6 +15,7 @@ import java.security.ProtectionDomain;
  * further use on Java 1.3 / 1.4
  * 
  * @author Alexandre Vasseur
+ * @author Andy Clement
  */
 public interface ClassPreProcessor {
 
@@ -26,14 +24,7 @@ public interface ClassPreProcessor {
         */
        void initialize();
 
-       /**
-        * Weave
-        * 
-        * @param className
-        * @param bytes
-        * @param classLoader
-        * @param a protection domain that may be used for defining extraneous classes generated as part of modifying the one passed in
-        * @return
-        */
        byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader, ProtectionDomain protectionDomain);
+
+       void prepareForRedefinition(ClassLoader loader, String className);
 }
\ No newline at end of file
index ae5a999c9d83eabfc8dacf3193648d80b2ca3ca2..a3201816a3e19419064beb4e52fab773c591a983 100644 (file)
@@ -1,13 +1,10 @@
 /*******************************************************************************
- * Copyright (c) 2005 Contributors.
+ * Copyright (c) 2005,2018 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://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Alexandre Vasseur         initial implementation
  *******************************************************************************/
 package org.aspectj.weaver.loadtime;
 
@@ -18,19 +15,17 @@ import java.security.ProtectionDomain;
 /**
  * Java 1.5 adapter for class pre processor
  * 
- * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
+ * @author Alexandre Vasseur
+ * @author Andy Clement
  */
 public class ClassPreProcessorAgentAdapter implements ClassFileTransformer {
 
-       /**
-        * Concrete preprocessor.
-        */
-       private static ClassPreProcessor s_preProcessor;
+       private static ClassPreProcessor classPreProcessor;
 
        static {
                try {
-                       s_preProcessor = new Aj();
-                       s_preProcessor.initialize();
+                       classPreProcessor = new Aj();
+                       classPreProcessor.initialize();
                } catch (Exception e) {
                        throw new ExceptionInInitializerError("could not initialize JSR163 preprocessor due to: " + e.toString());
                }
@@ -46,11 +41,13 @@ public class ClassPreProcessorAgentAdapter implements ClassFileTransformer {
         * @param bytes the incoming bytes (before weaving)
         * @return the woven bytes
         */
+       @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                        byte[] bytes) throws IllegalClassFormatException {
                if (classBeingRedefined != null) {
                        System.err.println("INFO: (Enh120375):  AspectJ attempting reweave of '" + className + "'");
+                       classPreProcessor.prepareForRedefinition(loader, className);
                }
-               return s_preProcessor.preProcess(className, bytes, loader, protectionDomain);
+               return classPreProcessor.preProcess(className, bytes, loader, protectionDomain);
        }
 }