You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by jd...@apache.org on 2025/07/17 22:36:36 UTC

(grails-core) 01/01: remove old asm & AnnotationMetadataReader supporting classes; adopt Spring's SimpleMetadataReaderFactory instead - see https://github.com/spring-projects/spring-framework/wiki/MergedAnnotation-API-internals?utm_source=chatgpt.com

This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch mergedAnnotationsApi
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit e48a54c99f2ee14cde96ddc71536753cf7a30019
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Thu Jul 17 16:36:20 2025 -0600

    remove old asm & AnnotationMetadataReader supporting classes; adopt Spring's SimpleMetadataReaderFactory instead
    - see https://github.com/spring-projects/spring-framework/wiki/MergedAnnotation-API-internals?utm_source=chatgpt.com
---
 LICENSE                                            |   29 -
 NOTICE                                             |    9 -
 .../AbstractRecursiveAnnotationVisitor.java        |  108 --
 .../AnnotationAttributesReadingVisitor.java        |  131 ---
 .../AnnotationMetadataReadingVisitor.java          |  207 ----
 .../annotation/AnnotationReadingVisitorUtils.java  |  176 ----
 .../annotation/ClassMetadataReadingVisitor.java    |  246 -----
 .../annotation/MethodMetadataReadingVisitor.java   |  176 ----
 .../RecursiveAnnotationArrayVisitor.java           |  112 ---
 .../RecursiveAnnotationAttributesVisitor.java      |   55 -
 .../compiler/asm/AnnotationMetadataReader.java     |  142 ---
 .../grails/common/compiler/asm/Attribute.java      |  258 -----
 .../grails/common/compiler/asm/ByteVector.java     |  339 -------
 .../grails/common/compiler/asm/ClassReader.java    | 1056 --------------------
 .../apache/grails/common/compiler/asm/Context.java |  146 ---
 .../grails/common/compiler/asm/TypePath.java       |  196 ----
 grails-common/src/main/resources/META-INF/LICENSE  |  233 -----
 grails-common/src/main/resources/META-INF/NOTICE   |   18 -
 .../boot/config/tools/ClassPathScanner.groovy      |    6 +-
 .../utils/AnnotationMetadataReaderFactory.java     |   39 -
 .../gorm/utils/ClasspathEntityScanner.groovy       |    3 +-
 licenses/LICENSE-asm.txt                           |   27 -
 22 files changed, 6 insertions(+), 3706 deletions(-)

diff --git a/LICENSE b/LICENSE
index 06f77ceaab..1e51fd6e2a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -203,20 +203,6 @@
 
 --------------------------------------------------------------------------
 
-BSD License
-
-The following classes within this product:
-
-    org.apache.grails.common.compiler.asm.Attribute
-    org.apache.grails.common.compiler.asm.ByteVector
-    org.apache.grails.common.compiler.asm.ClassReader
-    org.apache.grails.common.compiler.asm.Context
-    org.apache.grails.common.compiler.asm.TypePath
-
-See the LICENSE/licenses-asm.txt file for the ASM license terms.
-
---------------------------------------------------------------------------
-
 Public Domain
 
 The following classes within this product:
@@ -250,21 +236,6 @@ See licenses/LICENSE-CDDL.txt for the full license terms.
 
 --------------------------------------------------------------------------
 
-This product includes the following files from Spring Framework 5.3, developed by Pivotal Software, Inc., licensed under the Apache License 2.0:
-
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java
-    grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java
-
-See the above Apache License 2.0 for the terms governing these files.
-
---------------------------------------------------------------------------
-
 This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/). It uses Sitemesh2,
 licensed under the OpenSymphony Software License, Version 1.1.
 
diff --git a/NOTICE b/NOTICE
index b78f70d549..d5e4c5dbbf 100644
--- a/NOTICE
+++ b/NOTICE
@@ -8,11 +8,6 @@ The Apache Software Foundation (http://www.apache.org/).
 Additional Licenses
 ------------------
 
-ASM Library
-This product includes software from ASM Library, licensed under BSD License.
-Copyright 2000-2011 INRIA, France Telecom.
-See licenses/LICENSE-asm.txt for the full license terms.
-
 Project Reactor
 This product includes software from Project Reactor, licensed under Apache License, Version 2.0.
 2011-2014 Pivotal Software, Inc.
@@ -23,9 +18,5 @@ The original XML Schemas for Java EE Deployment Descriptors:
 may be obtained from:
 http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html
 
-This product includes software from Spring Framework 5.3, developed by Pivotal Software, Inc.
-Copyright 2002-2020 the original author or authors.
-See the LICENSE file for the Apache License 2.0 terms.
-
 This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/). It uses Sitemesh2,
 licensed under the OpenSymphony Software License, Version 1.1. See licenses/LICENSE-opensymphony.txt for the full license terms.
\ No newline at end of file
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java
deleted file mode 100644
index a810868fd4..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.lang.reflect.Field;
-import java.security.AccessControlException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.SpringAsmInfo;
-import org.springframework.asm.Type;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.lang.Nullable;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.ReflectionUtils;
-
-/**
- * {@link AnnotationVisitor} to recursively visit annotations.
-
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Chris Beams
- * @author Juergen Hoeller
- * @author Phillip Webb
- * @author Sam Brannen
- * @since 3.1.1
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
-
-    protected final Log logger = LogFactory.getLog(getClass());
-
-    protected final AnnotationAttributes attributes;
-
-    @Nullable
-    protected final ClassLoader classLoader;
-
-
-    public AbstractRecursiveAnnotationVisitor(@Nullable ClassLoader classLoader, AnnotationAttributes attributes) {
-        super(SpringAsmInfo.ASM_VERSION);
-        this.classLoader = classLoader;
-        this.attributes = attributes;
-    }
-
-
-    @Override
-    public void visit(String attributeName, Object attributeValue) {
-        this.attributes.put(attributeName, attributeValue);
-    }
-
-    @Override
-    public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) {
-        String annotationType = Type.getType(asmTypeDescriptor).getClassName();
-        AnnotationAttributes nestedAttributes = new AnnotationAttributes(annotationType, this.classLoader);
-        this.attributes.put(attributeName, nestedAttributes);
-        return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader);
-    }
-
-    @Override
-    public AnnotationVisitor visitArray(String attributeName) {
-        return new RecursiveAnnotationArrayVisitor(attributeName, this.attributes, this.classLoader);
-    }
-
-    @Override
-    public void visitEnum(String attributeName, String asmTypeDescriptor, String attributeValue) {
-        Object newValue = getEnumValue(asmTypeDescriptor, attributeValue);
-        visit(attributeName, newValue);
-    }
-
-    protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) {
-        Object valueToUse = attributeValue;
-        try {
-            Class<?> enumType = ClassUtils.forName(Type.getType(asmTypeDescriptor).getClassName(), this.classLoader);
-            Field enumConstant = ReflectionUtils.findField(enumType, attributeValue);
-            if (enumConstant != null) {
-                ReflectionUtils.makeAccessible(enumConstant);
-                valueToUse = enumConstant.get(null);
-            }
-        }
-        catch (ClassNotFoundException | NoClassDefFoundError ex) {
-            logger.debug("Failed to classload enum type while reading annotation metadata", ex);
-        }
-        catch (IllegalAccessException | AccessControlException ex) {
-            logger.debug("Could not access enum value while reading annotation metadata", ex);
-        }
-        return valueToUse;
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java
deleted file mode 100644
index 91e4bad1d0..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Modifier;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.lang.Nullable;
-import org.springframework.util.MultiValueMap;
-import org.springframework.util.ObjectUtils;
-
-/**
- * ASM visitor which looks for annotations defined on a class or method,
- * including meta-annotations.
- *
- * <p>This visitor is fully recursive, taking into account any nested
- * annotations or nested annotation arrays.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Juergen Hoeller
- * @author Chris Beams
- * @author Phillip Webb
- * @author Sam Brannen
- * @since 3.0
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttributesVisitor {
-
-    private final MultiValueMap<String, AnnotationAttributes> attributesMap;
-
-    private final Map<String, Set<String>> metaAnnotationMap;
-
-
-    public AnnotationAttributesReadingVisitor(String annotationType,
-                                              MultiValueMap<String, AnnotationAttributes> attributesMap, Map<String, Set<String>> metaAnnotationMap,
-                                              @Nullable ClassLoader classLoader) {
-
-        super(annotationType, new AnnotationAttributes(annotationType, classLoader), classLoader);
-        this.attributesMap = attributesMap;
-        this.metaAnnotationMap = metaAnnotationMap;
-    }
-
-
-    @Override
-    public void visitEnd() {
-        super.visitEnd();
-
-        Class<? extends Annotation> annotationClass = this.attributes.annotationType();
-        if (annotationClass != null) {
-            List<AnnotationAttributes> attributeList = this.attributesMap.get(this.annotationType);
-            if (attributeList == null) {
-                this.attributesMap.add(this.annotationType, this.attributes);
-            }
-            else {
-                attributeList.add(0, this.attributes);
-            }
-            if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) {
-                try {
-                    Annotation[] metaAnnotations = annotationClass.getAnnotations();
-                    if (!ObjectUtils.isEmpty(metaAnnotations)) {
-                        Set<Annotation> visited = new LinkedHashSet<>();
-                        for (Annotation metaAnnotation : metaAnnotations) {
-                            recursivelyCollectMetaAnnotations(visited, metaAnnotation);
-                        }
-                        if (!visited.isEmpty()) {
-                            Set<String> metaAnnotationTypeNames = new LinkedHashSet<>(visited.size());
-                            for (Annotation ann : visited) {
-                                metaAnnotationTypeNames.add(ann.annotationType().getName());
-                            }
-                            this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
-                        }
-                    }
-                }
-                catch (Throwable ex) {
-                    if (logger.isDebugEnabled()) {
-                        logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex);
-                    }
-                }
-            }
-        }
-    }
-
-    private void recursivelyCollectMetaAnnotations(Set<Annotation> visited, Annotation annotation) {
-        Class<? extends Annotation> annotationType = annotation.annotationType();
-        String annotationName = annotationType.getName();
-        if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && visited.add(annotation)) {
-            try {
-                // Only do attribute scanning for public annotations; we'd run into
-                // IllegalAccessExceptions otherwise, and we don't want to mess with
-                // accessibility in a SecurityManager environment.
-                if (Modifier.isPublic(annotationType.getModifiers())) {
-                    this.attributesMap.add(annotationName,
-                            AnnotationUtils.getAnnotationAttributes(annotation, false, true));
-                }
-                for (Annotation metaMetaAnnotation : annotationType.getAnnotations()) {
-                    recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation);
-                }
-            }
-            catch (Throwable ex) {
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Failed to introspect meta-annotations on " + annotation + ": " + ex);
-                }
-            }
-        }
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java
deleted file mode 100644
index 664ba4afd2..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.MethodVisitor;
-import org.springframework.asm.Opcodes;
-import org.springframework.asm.Type;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.core.annotation.MergedAnnotations;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.core.type.MethodMetadata;
-import org.springframework.lang.Nullable;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-
-/**
- * ASM class visitor which looks for the class name and implemented types as
- * well as for the annotations defined on the class, exposing them through
- * the {@link org.springframework.core.type.AnnotationMetadata} interface.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Juergen Hoeller
- * @author Mark Fisher
- * @author Costin Leau
- * @author Phillip Webb
- * @author Sam Brannen
- * @since 2.5
- * @deprecated As of Spring Framework 5.2, this class has been replaced by
- * SimpleAnnotationMetadataReadingVisitor for internal use within the
- * framework, but there is no public replacement for
- * {@code AnnotationMetadataReadingVisitor}.
- */
-@Deprecated
-public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata {
-
-    @Nullable
-    protected final ClassLoader classLoader;
-
-    protected final Set<String> annotationSet = new LinkedHashSet<>(4);
-
-    protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<>(4);
-
-    /**
-     * Declared as a {@link LinkedMultiValueMap} instead of a {@link MultiValueMap}
-     * to ensure that the hierarchical ordering of the entries is preserved.
-     * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes
-     */
-    protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<>(3);
-
-    protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<>(4);
-
-
-    public AnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) {
-        this.classLoader = classLoader;
-    }
-
-
-    @Override
-    public MergedAnnotations getAnnotations() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        // Skip bridge methods - we're only interested in original annotation-defining user methods.
-        // On JDK 8, we'd otherwise run into double detection of the same annotated method...
-        if ((access & Opcodes.ACC_BRIDGE) != 0) {
-            return super.visitMethod(access, name, desc, signature, exceptions);
-        }
-        return new MethodMetadataReadingVisitor(name, access, getClassName(),
-                Type.getReturnType(desc).getClassName(), this.classLoader, this.methodMetadataSet);
-    }
-
-    @Override
-    @Nullable
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        if (!visible) {
-            return null;
-        }
-        String className = Type.getType(desc).getClassName();
-        if (AnnotationUtils.isInJavaLangAnnotationPackage(className)) {
-            return null;
-        }
-        this.annotationSet.add(className);
-        return new AnnotationAttributesReadingVisitor(
-                className, this.attributesMap, this.metaAnnotationMap, this.classLoader);
-    }
-
-
-    @Override
-    public Set<String> getAnnotationTypes() {
-        return this.annotationSet;
-    }
-
-    @Override
-    public Set<String> getMetaAnnotationTypes(String annotationName) {
-        Set<String> metaAnnotationTypes = this.metaAnnotationMap.get(annotationName);
-        return (metaAnnotationTypes != null ? metaAnnotationTypes : Collections.emptySet());
-    }
-
-    @Override
-    public boolean hasMetaAnnotation(String metaAnnotationType) {
-        if (AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotationType)) {
-            return false;
-        }
-        Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values();
-        for (Set<String> metaTypes : allMetaTypes) {
-            if (metaTypes.contains(metaAnnotationType)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isAnnotated(String annotationName) {
-        return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) &&
-                this.attributesMap.containsKey(annotationName));
-    }
-
-    @Override
-    public boolean hasAnnotation(String annotationName) {
-        return getAnnotationTypes().contains(annotationName);
-    }
-
-    @Override
-    @Nullable
-    public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
-        AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
-                this.attributesMap, this.metaAnnotationMap, annotationName);
-        if (raw == null) {
-            return null;
-        }
-        return AnnotationReadingVisitorUtils.convertClassValues(
-                "class '" + getClassName() + "'", this.classLoader, raw, classValuesAsString);
-    }
-
-    @Override
-    @Nullable
-    public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
-        MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<>();
-        List<AnnotationAttributes> attributes = this.attributesMap.get(annotationName);
-        if (attributes == null) {
-            return null;
-        }
-        String annotatedElement = "class '" + getClassName() + "'";
-        for (AnnotationAttributes raw : attributes) {
-            for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues(
-                    annotatedElement, this.classLoader, raw, classValuesAsString).entrySet()) {
-                allAttributes.add(entry.getKey(), entry.getValue());
-            }
-        }
-        return allAttributes;
-    }
-
-    @Override
-    public boolean hasAnnotatedMethods(String annotationName) {
-        for (MethodMetadata methodMetadata : this.methodMetadataSet) {
-            if (methodMetadata.isAnnotated(annotationName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
-        Set<MethodMetadata> annotatedMethods = new LinkedHashSet<>(4);
-        for (MethodMetadata methodMetadata : this.methodMetadataSet) {
-            if (methodMetadata.isAnnotated(annotationName)) {
-                annotatedMethods.add(methodMetadata);
-            }
-        }
-        return annotatedMethods;
-    }
-
-    @Override
-    public Set<MethodMetadata> getDeclaredMethods() {
-        return Set.of();
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java
deleted file mode 100644
index 7b20f290af..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.asm.Type;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.lang.Nullable;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.ObjectUtils;
-
-/**
- * Internal utility class used when reading annotations via ASM.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Juergen Hoeller
- * @author Mark Fisher
- * @author Costin Leau
- * @author Phillip Webb
- * @author Sam Brannen
- * @since 4.0
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-abstract class AnnotationReadingVisitorUtils {
-
-    public static AnnotationAttributes convertClassValues(Object annotatedElement,
-                                                          @Nullable ClassLoader classLoader, AnnotationAttributes original, boolean classValuesAsString) {
-
-        AnnotationAttributes result = new AnnotationAttributes(original);
-        AnnotationUtils.postProcessAnnotationAttributes(annotatedElement, result, classValuesAsString);
-
-        for (Map.Entry<String, Object> entry : result.entrySet()) {
-            try {
-                Object value = entry.getValue();
-                if (value instanceof AnnotationAttributes) {
-                    value = convertClassValues(
-                            annotatedElement, classLoader, (AnnotationAttributes) value, classValuesAsString);
-                }
-                else if (value instanceof AnnotationAttributes[]) {
-                    AnnotationAttributes[] values = (AnnotationAttributes[]) value;
-                    for (int i = 0; i < values.length; i++) {
-                        values[i] = convertClassValues(annotatedElement, classLoader, values[i], classValuesAsString);
-                    }
-                    value = values;
-                }
-                else if (value instanceof Type) {
-                    value = (classValuesAsString ? ((Type) value).getClassName() :
-                            ClassUtils.forName(((Type) value).getClassName(), classLoader));
-                }
-                else if (value instanceof Type[]) {
-                    Type[] array = (Type[]) value;
-                    Object[] convArray =
-                            (classValuesAsString ? new String[array.length] : new Class<?>[array.length]);
-                    for (int i = 0; i < array.length; i++) {
-                        convArray[i] = (classValuesAsString ? array[i].getClassName() :
-                                ClassUtils.forName(array[i].getClassName(), classLoader));
-                    }
-                    value = convArray;
-                }
-                else if (classValuesAsString) {
-                    if (value instanceof Class) {
-                        value = ((Class<?>) value).getName();
-                    }
-                    else if (value instanceof Class[]) {
-                        Class<?>[] clazzArray = (Class<?>[]) value;
-                        String[] newValue = new String[clazzArray.length];
-                        for (int i = 0; i < clazzArray.length; i++) {
-                            newValue[i] = clazzArray[i].getName();
-                        }
-                        value = newValue;
-                    }
-                }
-                entry.setValue(value);
-            }
-            catch (Throwable ex) {
-                // Class not found - can't resolve class reference in annotation attribute.
-                result.put(entry.getKey(), ex);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Retrieve the merged attributes of the annotation of the given type,
-     * if any, from the supplied {@code attributesMap}.
-     * <p>Annotation attribute values appearing <em>lower</em> in the annotation
-     * hierarchy (i.e., closer to the declaring class) will override those
-     * defined <em>higher</em> in the annotation hierarchy.
-     * @param attributesMap the map of annotation attribute lists, keyed by
-     * annotation type name
-     * @param metaAnnotationMap the map of meta annotation relationships,
-     * keyed by annotation type name
-     * @param annotationName the fully qualified class name of the annotation
-     * type to look for
-     * @return the merged annotation attributes, or {@code null} if no
-     * matching annotation is present in the {@code attributesMap}
-     * @since 4.0.3
-     */
-    @Nullable
-    public static AnnotationAttributes getMergedAnnotationAttributes(
-            LinkedMultiValueMap<String, AnnotationAttributes> attributesMap,
-            Map<String, Set<String>> metaAnnotationMap, String annotationName) {
-
-        // Get the unmerged list of attributes for the target annotation.
-        List<AnnotationAttributes> attributesList = attributesMap.get(annotationName);
-        if (CollectionUtils.isEmpty(attributesList)) {
-            return null;
-        }
-
-        // To start with, we populate the result with a copy of all attribute values
-        // from the target annotation. A copy is necessary so that we do not
-        // inadvertently mutate the state of the metadata passed to this method.
-        AnnotationAttributes result = new AnnotationAttributes(attributesList.get(0));
-
-        Set<String> overridableAttributeNames = new HashSet<>(result.keySet());
-        overridableAttributeNames.remove(AnnotationUtils.VALUE);
-
-        // Since the map is a LinkedMultiValueMap, we depend on the ordering of
-        // elements in the map and reverse the order of the keys in order to traverse
-        // "down" the annotation hierarchy.
-        List<String> annotationTypes = new ArrayList<>(attributesMap.keySet());
-        Collections.reverse(annotationTypes);
-
-        // No need to revisit the target annotation type:
-        annotationTypes.remove(annotationName);
-
-        for (String currentAnnotationType : annotationTypes) {
-            List<AnnotationAttributes> currentAttributesList = attributesMap.get(currentAnnotationType);
-            if (!ObjectUtils.isEmpty(currentAttributesList)) {
-                Set<String> metaAnns = metaAnnotationMap.get(currentAnnotationType);
-                if (metaAnns != null && metaAnns.contains(annotationName)) {
-                    AnnotationAttributes currentAttributes = currentAttributesList.get(0);
-                    for (String overridableAttributeName : overridableAttributeNames) {
-                        Object value = currentAttributes.get(overridableAttributeName);
-                        if (value != null) {
-                            // Store the value, potentially overriding a value from an attribute
-                            // of the same name found higher in the annotation hierarchy.
-                            result.put(overridableAttributeName, value);
-                        }
-                    }
-                }
-            }
-        }
-
-        return result;
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java
deleted file mode 100644
index c51cf9414e..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.Attribute;
-import org.springframework.asm.ClassVisitor;
-import org.springframework.asm.FieldVisitor;
-import org.springframework.asm.MethodVisitor;
-import org.springframework.asm.Opcodes;
-import org.springframework.asm.SpringAsmInfo;
-import org.springframework.core.type.ClassMetadata;
-import org.springframework.lang.Nullable;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.StringUtils;
-
-/**
- * ASM class visitor which looks only for the class name and implemented types,
- * exposing them through the {@link org.springframework.core.type.ClassMetadata}
- * interface.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Rod Johnson
- * @author Costin Leau
- * @author Mark Fisher
- * @author Ramnivas Laddad
- * @author Chris Beams
- * @since 2.5
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {
-
-    private String className = "";
-
-    private boolean isInterface;
-
-    private boolean isAnnotation;
-
-    private boolean isAbstract;
-
-    private boolean isFinal;
-
-    @Nullable
-    private String enclosingClassName;
-
-    private boolean independentInnerClass;
-
-    @Nullable
-    private String superClassName;
-
-    private String[] interfaces = new String[0];
-
-    private Set<String> memberClassNames = new LinkedHashSet<>(4);
-
-
-    public ClassMetadataReadingVisitor() {
-        super(SpringAsmInfo.ASM_VERSION);
-    }
-
-
-    @Override
-    public void visit(
-            int version, int access, String name, String signature, @Nullable String supername, String[] interfaces) {
-
-        this.className = ClassUtils.convertResourcePathToClassName(name);
-        this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0);
-        this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0);
-        this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0);
-        this.isFinal = ((access & Opcodes.ACC_FINAL) != 0);
-        if (supername != null && !this.isInterface) {
-            this.superClassName = ClassUtils.convertResourcePathToClassName(supername);
-        }
-        this.interfaces = new String[interfaces.length];
-        for (int i = 0; i < interfaces.length; i++) {
-            this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]);
-        }
-    }
-
-    @Override
-    public void visitOuterClass(String owner, String name, String desc) {
-        this.enclosingClassName = ClassUtils.convertResourcePathToClassName(owner);
-    }
-
-    @Override
-    public void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) {
-        if (outerName != null) {
-            String fqName = ClassUtils.convertResourcePathToClassName(name);
-            String fqOuterName = ClassUtils.convertResourcePathToClassName(outerName);
-            if (this.className.equals(fqName)) {
-                this.enclosingClassName = fqOuterName;
-                this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);
-            }
-            else if (this.className.equals(fqOuterName)) {
-                this.memberClassNames.add(fqName);
-            }
-        }
-    }
-
-    @Override
-    public void visitSource(String source, String debug) {
-        // no-op
-    }
-
-    @Override
-    @Nullable
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        // no-op
-        return new EmptyAnnotationVisitor();
-    }
-
-    @Override
-    public void visitAttribute(Attribute attr) {
-        // no-op
-    }
-
-    @Override
-    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
-        // no-op
-        return new EmptyFieldVisitor();
-    }
-
-    @Override
-    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        // no-op
-        return new EmptyMethodVisitor();
-    }
-
-    @Override
-    public void visitEnd() {
-        // no-op
-    }
-
-
-    @Override
-    public String getClassName() {
-        return this.className;
-    }
-
-    @Override
-    public boolean isInterface() {
-        return this.isInterface;
-    }
-
-    @Override
-    public boolean isAnnotation() {
-        return this.isAnnotation;
-    }
-
-    @Override
-    public boolean isAbstract() {
-        return this.isAbstract;
-    }
-
-    @Override
-    public boolean isFinal() {
-        return this.isFinal;
-    }
-
-    @Override
-    public boolean isIndependent() {
-        return (this.enclosingClassName == null || this.independentInnerClass);
-    }
-
-    @Override
-    public boolean hasEnclosingClass() {
-        return (this.enclosingClassName != null);
-    }
-
-    @Override
-    @Nullable
-    public String getEnclosingClassName() {
-        return this.enclosingClassName;
-    }
-
-    @Override
-    @Nullable
-    public String getSuperClassName() {
-        return this.superClassName;
-    }
-
-    @Override
-    public String[] getInterfaceNames() {
-        return this.interfaces;
-    }
-
-    @Override
-    public String[] getMemberClassNames() {
-        return StringUtils.toStringArray(this.memberClassNames);
-    }
-
-
-    private static class EmptyAnnotationVisitor extends AnnotationVisitor {
-
-        public EmptyAnnotationVisitor() {
-            super(SpringAsmInfo.ASM_VERSION);
-        }
-
-        @Override
-        public AnnotationVisitor visitAnnotation(String name, String desc) {
-            return this;
-        }
-
-        @Override
-        public AnnotationVisitor visitArray(String name) {
-            return this;
-        }
-    }
-
-
-    private static class EmptyMethodVisitor extends MethodVisitor {
-
-        public EmptyMethodVisitor() {
-            super(SpringAsmInfo.ASM_VERSION);
-        }
-    }
-
-
-    private static class EmptyFieldVisitor extends FieldVisitor {
-
-        public EmptyFieldVisitor() {
-            super(SpringAsmInfo.ASM_VERSION);
-        }
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java
deleted file mode 100644
index 9e06949c6a..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.MethodVisitor;
-import org.springframework.asm.Opcodes;
-import org.springframework.asm.SpringAsmInfo;
-import org.springframework.asm.Type;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.annotation.MergedAnnotations;
-import org.springframework.core.type.MethodMetadata;
-import org.springframework.lang.Nullable;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-
-/**
- * ASM method visitor which looks for the annotations defined on a method,
- * exposing them through the {@link org.springframework.core.type.MethodMetadata}
- * interface.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Juergen Hoeller
- * @author Mark Pollack
- * @author Costin Leau
- * @author Chris Beams
- * @author Phillip Webb
- * @since 3.0
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-public class MethodMetadataReadingVisitor extends MethodVisitor implements MethodMetadata {
-
-    protected final String methodName;
-
-    protected final int access;
-
-    protected final String declaringClassName;
-
-    protected final String returnTypeName;
-
-    @Nullable
-    protected final ClassLoader classLoader;
-
-    protected final Set<MethodMetadata> methodMetadataSet;
-
-    protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<>(4);
-
-    protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<>(3);
-
-
-    public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName,
-                                        String returnTypeName, @Nullable ClassLoader classLoader, Set<MethodMetadata> methodMetadataSet) {
-
-        super(SpringAsmInfo.ASM_VERSION);
-        this.methodName = methodName;
-        this.access = access;
-        this.declaringClassName = declaringClassName;
-        this.returnTypeName = returnTypeName;
-        this.classLoader = classLoader;
-        this.methodMetadataSet = methodMetadataSet;
-    }
-
-
-    @Override
-    public MergedAnnotations getAnnotations() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    @Nullable
-    public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
-        if (!visible) {
-            return null;
-        }
-        this.methodMetadataSet.add(this);
-        String className = Type.getType(desc).getClassName();
-        return new AnnotationAttributesReadingVisitor(
-                className, this.attributesMap, this.metaAnnotationMap, this.classLoader);
-    }
-
-
-    @Override
-    public String getMethodName() {
-        return this.methodName;
-    }
-
-    @Override
-    public boolean isAbstract() {
-        return ((this.access & Opcodes.ACC_ABSTRACT) != 0);
-    }
-
-    @Override
-    public boolean isStatic() {
-        return ((this.access & Opcodes.ACC_STATIC) != 0);
-    }
-
-    @Override
-    public boolean isFinal() {
-        return ((this.access & Opcodes.ACC_FINAL) != 0);
-    }
-
-    @Override
-    public boolean isOverridable() {
-        return (!isStatic() && !isFinal() && ((this.access & Opcodes.ACC_PRIVATE) == 0));
-    }
-
-    @Override
-    public boolean isAnnotated(String annotationName) {
-        return this.attributesMap.containsKey(annotationName);
-    }
-
-    @Override
-    @Nullable
-    public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
-        AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
-                this.attributesMap, this.metaAnnotationMap, annotationName);
-        if (raw == null) {
-            return null;
-        }
-        return AnnotationReadingVisitorUtils.convertClassValues(
-                "method '" + getMethodName() + "'", this.classLoader, raw, classValuesAsString);
-    }
-
-    @Override
-    @Nullable
-    public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
-        if (!this.attributesMap.containsKey(annotationName)) {
-            return null;
-        }
-        MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<>();
-        List<AnnotationAttributes> attributesList = this.attributesMap.get(annotationName);
-        if (attributesList != null) {
-            String annotatedElement = "method '" + getMethodName() + '\'';
-            for (AnnotationAttributes annotationAttributes : attributesList) {
-                AnnotationAttributes convertedAttributes = AnnotationReadingVisitorUtils.convertClassValues(
-                        annotatedElement, this.classLoader, annotationAttributes, classValuesAsString);
-                convertedAttributes.forEach(allAttributes::add);
-            }
-        }
-        return allAttributes;
-    }
-
-    @Override
-    public String getDeclaringClassName() {
-        return this.declaringClassName;
-    }
-
-    @Override
-    public String getReturnTypeName() {
-        return this.returnTypeName;
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java
deleted file mode 100644
index d7ee022739..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.Type;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.lang.Nullable;
-import org.springframework.util.ObjectUtils;
-
-/**
- * {@link AnnotationVisitor} to recursively visit annotation arrays.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Chris Beams
- * @author Juergen Hoeller
- * @since 3.1.1
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationVisitor {
-
-    private final String attributeName;
-
-    private final List<AnnotationAttributes> allNestedAttributes = new ArrayList<>();
-
-
-    public RecursiveAnnotationArrayVisitor(
-            String attributeName, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) {
-
-        super(classLoader, attributes);
-        this.attributeName = attributeName;
-    }
-
-
-    @Override
-    public void visit(String attributeName, Object attributeValue) {
-        Object newValue = attributeValue;
-        Object existingValue = this.attributes.get(this.attributeName);
-        if (existingValue != null) {
-            newValue = ObjectUtils.addObjectToArray((Object[]) existingValue, newValue);
-        }
-        else {
-            Class<?> arrayClass = newValue.getClass();
-            if (Enum.class.isAssignableFrom(arrayClass)) {
-                while (arrayClass.getSuperclass() != null && !arrayClass.isEnum()) {
-                    arrayClass = arrayClass.getSuperclass();
-                }
-            }
-            Object[] newArray = (Object[]) Array.newInstance(arrayClass, 1);
-            newArray[0] = newValue;
-            newValue = newArray;
-        }
-        this.attributes.put(this.attributeName, newValue);
-    }
-
-    @Override
-    public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) {
-        String annotationType = Type.getType(asmTypeDescriptor).getClassName();
-        AnnotationAttributes nestedAttributes = new AnnotationAttributes(annotationType, this.classLoader);
-        this.allNestedAttributes.add(nestedAttributes);
-        return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader);
-    }
-
-    @Override
-    public void visitEnd() {
-        if (!this.allNestedAttributes.isEmpty()) {
-            this.attributes.put(this.attributeName, this.allNestedAttributes.toArray(new AnnotationAttributes[0]));
-        }
-        else if (!this.attributes.containsKey(this.attributeName)) {
-            Class<? extends Annotation> annotationType = this.attributes.annotationType();
-            if (annotationType != null) {
-                try {
-                    Class<?> attributeType = annotationType.getMethod(this.attributeName).getReturnType();
-                    if (attributeType.isArray()) {
-                        Class<?> elementType = attributeType.getComponentType();
-                        if (elementType.isAnnotation()) {
-                            elementType = AnnotationAttributes.class;
-                        }
-                        this.attributes.put(this.attributeName, Array.newInstance(elementType, 0));
-                    }
-                }
-                catch (NoSuchMethodException ex) {
-                    // Corresponding attribute method not found: cannot expose empty array.
-                }
-            }
-        }
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java
deleted file mode 100644
index dc8b935d1a..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2002-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.grails.common.annotation;
-
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.lang.Nullable;
-
-/**
- * {@link AnnotationVisitor} to recursively visit annotation attributes.
- *
- * <p>Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was
- * removed in Spring 6 without a public replacement.
- *
- * @author Chris Beams
- * @author Juergen Hoeller
- * @since 3.1.1
- * @deprecated As of Spring Framework 5.2, this class and related classes in this
- * package have been replaced by SimpleAnnotationMetadataReadingVisitor
- * and related classes for internal use within the framework.
- */
-@Deprecated
-class RecursiveAnnotationAttributesVisitor extends AbstractRecursiveAnnotationVisitor {
-
-    protected final String annotationType;
-
-
-    public RecursiveAnnotationAttributesVisitor(
-            String annotationType, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) {
-
-        super(classLoader, attributes);
-        this.annotationType = annotationType;
-    }
-
-
-    @Override
-    public void visitEnd() {
-        AnnotationUtils.registerDefaultValues(this.attributes);
-    }
-
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java
deleted file mode 100644
index 98a5342bde..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.grails.common.compiler.asm;
-
-import org.apache.grails.common.annotation.AnnotationMetadataReadingVisitor;
-import org.springframework.asm.AnnotationVisitor;
-import org.springframework.asm.SpringAsmInfo;
-import org.springframework.asm.Type;
-import org.springframework.core.io.Resource;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.core.type.ClassMetadata;
-import org.springframework.core.type.classreading.MetadataReader;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A more limited version of Spring's annotation reader that only reads annotations on classes
- *
- * @author Graeme Rocher
- * @since 3.1.13
- */
-public class AnnotationMetadataReader implements MetadataReader {
-    private final Resource resource;
-
-    private final ClassMetadata classMetadata;
-
-    private final AnnotationMetadata annotationMetadata;
-
-    /**
-     * Reads only the annotation names from a class resource
-     * @param resource The resource
-     * @param classLoader The classloader
-     * @throws IOException
-     */
-    public AnnotationMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
-        this(resource, classLoader, false);
-    }
-    /**
-     * Constructs a new annotation metadata reader
-     *
-     * @param resource The resource
-     * @param classLoader The classloader
-     * @param readAttributeValues Whether to read the attributes in addition or just the annotation class names
-     * @throws IOException
-     */
-    public AnnotationMetadataReader(Resource resource, ClassLoader classLoader, boolean readAttributeValues) throws IOException {
-        InputStream is = new BufferedInputStream(resource.getInputStream());
-        ClassReader classReader;
-        try {
-            classReader = new ClassReader(is);
-        }
-        catch (IllegalArgumentException ex) {
-            throw new IOException("ASM ClassReader failed to parse class file - " +
-                    "probably due to a new Java class file version that isn't supported yet: " + resource, ex);
-        }
-        finally {
-            is.close();
-        }
-
-
-        AnnotationMetadataReadingVisitor visitor;
-
-        if(readAttributeValues) {
-            visitor = new AnnotationMetadataReadingVisitor(classLoader);
-        }
-        else {
-            visitor = new AnnotationMetadataReadingVisitor(classLoader) {
-                @Override
-                public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
-                    String className = Type.getType(desc).getClassName();
-                    this.annotationSet.add(className);
-                    return new EmptyAnnotationVisitor();
-                }
-            };
-        }
-        classReader.accept(visitor, ClassReader.SKIP_DEBUG);
-
-        this.annotationMetadata = visitor;
-        // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
-        this.classMetadata = visitor;
-        this.resource = resource;
-    }
-
-
-    @Override
-    public Resource getResource() {
-        return this.resource;
-    }
-
-    @Override
-    public ClassMetadata getClassMetadata() {
-        return this.classMetadata;
-    }
-
-    @Override
-    public AnnotationMetadata getAnnotationMetadata() {
-        return this.annotationMetadata;
-    }
-
-    private static class EmptyAnnotationVisitor extends AnnotationVisitor {
-
-        EmptyAnnotationVisitor() {
-            super(loadAsmVersion());
-        }
-
-        private static int loadAsmVersion() {
-            try {
-                // Load the ASM version using reflection to prevent the compiler from replacing the reference
-                // with the value.  This it soupport different verisons of spring.
-                return (int) SpringAsmInfo.class.getField("ASM_VERSION").get(null);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public AnnotationVisitor visitAnnotation(String name, String desc) {
-            return this;
-        }
-
-        @Override
-        public AnnotationVisitor visitArray(String name) {
-            return this;
-        }
-    }
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java
deleted file mode 100644
index 356d618d19..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.grails.common.compiler.asm;
-
-import org.springframework.asm.ClassWriter;
-import org.springframework.asm.Label;
-
-/**
- * A non standard class, field, method or code attribute.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-class Attribute {
-
-    /**
-     * The type of this attribute.
-     */
-    public final String type;
-
-    /**
-     * The raw value of this attribute, used only for unknown attributes.
-     */
-    byte[] value;
-
-    /**
-     * The next attribute in this attribute list. May be <tt>null</tt>.
-     */
-    Attribute next;
-
-    /**
-     * Constructs a new empty attribute.
-     *
-     * @param type
-     *            the type of the attribute.
-     */
-    protected Attribute(final String type) {
-        this.type = type;
-    }
-
-    /**
-     * Returns <tt>true</tt> if this type of attribute is unknown. The default
-     * implementation of this method always returns <tt>true</tt>.
-     *
-     * @return <tt>true</tt> if this type of attribute is unknown.
-     */
-    public boolean isUnknown() {
-        return true;
-    }
-
-    /**
-     * Returns <tt>true</tt> if this type of attribute is a code attribute.
-     *
-     * @return <tt>true</tt> if this type of attribute is a code attribute.
-     */
-    public boolean isCodeAttribute() {
-        return false;
-    }
-
-    /**
-     * Returns the labels corresponding to this attribute.
-     *
-     * @return the labels corresponding to this attribute, or <tt>null</tt> if
-     *         this attribute is not a code attribute that contains labels.
-     */
-    protected Label[] getLabels() {
-        return null;
-    }
-
-    /**
-     * Reads a {@link #type type} attribute. This method must return a
-     * <i>new</i> {@link Attribute} object, of type {@link #type type},
-     * corresponding to the <tt>len</tt> bytes starting at the given offset, in
-     * the given class reader.
-     *
-     * @param cr
-     *            the class that contains the attribute to be read.
-     * @param off
-     *            index of the first byte of the attribute's content in
-     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param len
-     *            the length of the attribute's content.
-     * @param buf
-     *            buffer to be used to call {@link ClassReader#readUTF8
-     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
-     *            or {@link ClassReader#readConst readConst}.
-     * @param codeOff
-     *            index of the first byte of code's attribute content in
-     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
-     *            is not a code attribute. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param labels
-     *            the labels of the method's code, or <tt>null</tt> if the
-     *            attribute to be read is not a code attribute.
-     * @return a <i>new</i> {@link Attribute} object corresponding to the given
-     *         bytes.
-     */
-    protected Attribute read(final ClassReader cr, final int off,
-                             final int len, final char[] buf, final int codeOff,
-                             final Label[] labels) {
-        Attribute attr = new Attribute(type);
-        attr.value = new byte[len];
-        System.arraycopy(cr.b, off, attr.value, 0, len);
-        return attr;
-    }
-
-    /**
-     * Returns the byte array form of this attribute.
-     *
-     * @param cw
-     *            the class to which this attribute must be added. This
-     *            parameter can be used to add to the constant pool of this
-     *            class the items that corresponds to this attribute.
-     * @param code
-     *            the bytecode of the method corresponding to this code
-     *            attribute, or <tt>null</tt> if this attribute is not a code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to this
-     *            code attribute, or <tt>null</tt> if this attribute is not a
-     *            code attribute.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to this
-     *            code attribute, or -1 if this attribute is not a code
-     *            attribute.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to this code attribute, or -1 if this attribute
-     *            is not a code attribute.
-     * @return the byte array form of this attribute.
-     */
-    protected ByteVector write(final ClassWriter cw, final byte[] code,
-                               final int len, final int maxStack, final int maxLocals) {
-        ByteVector v = new ByteVector();
-        v.data = value;
-        v.length = value.length;
-        return v;
-    }
-
-    /**
-     * Returns the length of the attribute list that begins with this attribute.
-     *
-     * @return the length of the attribute list that begins with this attribute.
-     */
-    final int getCount() {
-        int count = 0;
-        Attribute attr = this;
-        while (attr != null) {
-            count += 1;
-            attr = attr.next;
-        }
-        return count;
-    }
-
-    /**
-     * Returns the size of all the attributes in this attribute list.
-     *
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @return the size of all the attributes in this attribute list. This size
-     *         includes the size of the attribute headers.
-     */
-    final int getSize(final ClassWriter cw, final byte[] code, final int len,
-                      final int maxStack, final int maxLocals) {
-        Attribute attr = this;
-        int size = 0;
-        while (attr != null) {
-            cw.newUTF8(attr.type);
-            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
-            attr = attr.next;
-        }
-        return size;
-    }
-
-    /**
-     * Writes all the attributes of this attribute list in the given byte
-     * vector.
-     *
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @param out
-     *            where the attributes must be written.
-     */
-    final void put(final ClassWriter cw, final byte[] code, final int len,
-                   final int maxStack, final int maxLocals, final ByteVector out) {
-        Attribute attr = this;
-        while (attr != null) {
-            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
-            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
-            out.putByteArray(b.data, 0, b.length);
-            attr = attr.next;
-        }
-    }
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java
deleted file mode 100644
index d3f08fdb14..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.grails.common.compiler.asm;
-
-/**
- * A dynamically extensible vector of bytes. This class is roughly equivalent to
- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
- * @author Eric Bruneton
- */
-class ByteVector {
-
-    /**
-     * The content of this vector.
-     */
-    byte[] data;
-
-    /**
-     * Actual number of bytes in this vector.
-     */
-    int length;
-
-    /**
-     * Constructs a new {@link ByteVector ByteVector} with a default initial
-     * size.
-     */
-    public ByteVector() {
-        data = new byte[64];
-    }
-
-    /**
-     * Constructs a new {@link ByteVector ByteVector} with the given initial
-     * size.
-     *
-     * @param initialSize
-     *            the initial size of the byte vector to be constructed.
-     */
-    public ByteVector(final int initialSize) {
-        data = new byte[initialSize];
-    }
-
-    /**
-     * Puts a byte into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param b
-     *            a byte.
-     * @return this byte vector.
-     */
-    public ByteVector putByte(final int b) {
-        int length = this.length;
-        if (length + 1 > data.length) {
-            enlarge(1);
-        }
-        data[length++] = (byte) b;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts two bytes into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param b1
-     *            a byte.
-     * @param b2
-     *            another byte.
-     * @return this byte vector.
-     */
-    ByteVector put11(final int b1, final int b2) {
-        int length = this.length;
-        if (length + 2 > data.length) {
-            enlarge(2);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) b1;
-        data[length++] = (byte) b2;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts a short into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param s
-     *            a short.
-     * @return this byte vector.
-     */
-    public ByteVector putShort(final int s) {
-        int length = this.length;
-        if (length + 2 > data.length) {
-            enlarge(2);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) (s >>> 8);
-        data[length++] = (byte) s;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts a byte and a short into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param b
-     *            a byte.
-     * @param s
-     *            a short.
-     * @return this byte vector.
-     */
-    ByteVector put12(final int b, final int s) {
-        int length = this.length;
-        if (length + 3 > data.length) {
-            enlarge(3);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) b;
-        data[length++] = (byte) (s >>> 8);
-        data[length++] = (byte) s;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts an int into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param i
-     *            an int.
-     * @return this byte vector.
-     */
-    public ByteVector putInt(final int i) {
-        int length = this.length;
-        if (length + 4 > data.length) {
-            enlarge(4);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts a long into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param l
-     *            a long.
-     * @return this byte vector.
-     */
-    public ByteVector putLong(final long l) {
-        int length = this.length;
-        if (length + 8 > data.length) {
-            enlarge(8);
-        }
-        byte[] data = this.data;
-        int i = (int) (l >>> 32);
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        i = (int) l;
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Puts an UTF8 string into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param s
-     *            a String whose UTF8 encoded length must be less than 65536.
-     * @return this byte vector.
-     */
-    public ByteVector putUTF8(final String s) {
-        int charLength = s.length();
-        if (charLength > 65535) {
-            throw new IllegalArgumentException();
-        }
-        int len = length;
-        if (len + 2 + charLength > data.length) {
-            enlarge(2 + charLength);
-        }
-        byte[] data = this.data;
-        // optimistic algorithm: instead of computing the byte length and then
-        // serializing the string (which requires two loops), we assume the byte
-        // length is equal to char length (which is the most frequent case), and
-        // we start serializing the string right away. During the serialization,
-        // if we find that this assumption is wrong, we continue with the
-        // general method.
-        data[len++] = (byte) (charLength >>> 8);
-        data[len++] = (byte) charLength;
-        for (int i = 0; i < charLength; ++i) {
-            char c = s.charAt(i);
-            if (c >= '\001' && c <= '\177') {
-                data[len++] = (byte) c;
-            } else {
-                length = len;
-                return encodeUTF8(s, i, 65535);
-            }
-        }
-        length = len;
-        return this;
-    }
-
-    /**
-     * Puts an UTF8 string into this byte vector. The byte vector is
-     * automatically enlarged if necessary. The string length is encoded in two
-     * bytes before the encoded characters, if there is space for that (i.e. if
-     * this.length - i - 2 >= 0).
-     *
-     * @param s
-     *            the String to encode.
-     * @param i
-     *            the index of the first character to encode. The previous
-     *            characters are supposed to have already been encoded, using
-     *            only one byte per character.
-     * @param maxByteLength
-     *            the maximum byte length of the encoded string, including the
-     *            already encoded characters.
-     * @return this byte vector.
-     */
-    ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
-        int charLength = s.length();
-        int byteLength = i;
-        char c;
-        for (int j = i; j < charLength; ++j) {
-            c = s.charAt(j);
-            if (c >= '\001' && c <= '\177') {
-                byteLength++;
-            } else if (c > '\u07FF') {
-                byteLength += 3;
-            } else {
-                byteLength += 2;
-            }
-        }
-        if (byteLength > maxByteLength) {
-            throw new IllegalArgumentException();
-        }
-        int start = length - i - 2;
-        if (start >= 0) {
-            data[start] = (byte) (byteLength >>> 8);
-            data[start + 1] = (byte) byteLength;
-        }
-        if (length + byteLength - i > data.length) {
-            enlarge(byteLength - i);
-        }
-        int len = length;
-        for (int j = i; j < charLength; ++j) {
-            c = s.charAt(j);
-            if (c >= '\001' && c <= '\177') {
-                data[len++] = (byte) c;
-            } else if (c > '\u07FF') {
-                data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
-                data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
-                data[len++] = (byte) (0x80 | c & 0x3F);
-            } else {
-                data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
-                data[len++] = (byte) (0x80 | c & 0x3F);
-            }
-        }
-        length = len;
-        return this;
-    }
-
-    /**
-     * Puts an array of bytes into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param b
-     *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
-     *            null bytes into this byte vector.
-     * @param off
-     *            index of the fist byte of b that must be copied.
-     * @param len
-     *            number of bytes of b that must be copied.
-     * @return this byte vector.
-     */
-    public ByteVector putByteArray(final byte[] b, final int off, final int len) {
-        if (length + len > data.length) {
-            enlarge(len);
-        }
-        if (b != null) {
-            System.arraycopy(b, off, data, length, len);
-        }
-        length += len;
-        return this;
-    }
-
-    /**
-     * Enlarge this byte vector so that it can receive n more bytes.
-     *
-     * @param size
-     *            number of additional bytes that this byte vector should be
-     *            able to receive.
-     */
-    private void enlarge(final int size) {
-        int length1 = 2 * data.length;
-        int length2 = length + size;
-        byte[] newData = new byte[length1 > length2 ? length1 : length2];
-        System.arraycopy(data, 0, newData, 0, length);
-        data = newData;
-    }
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java
deleted file mode 100644
index e7afd73883..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java
+++ /dev/null
@@ -1,1056 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.grails.common.compiler.asm;
-
-import org.springframework.asm.*;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A Java class parser to make a {@link org.springframework.asm.ClassVisitor} visit an existing class.
- * This class parses a byte array conforming to the Java class file format and
- * calls the appropriate visit methods of a given class visitor for each field,
- * method and bytecode instruction encountered.
- *
- * @author Eric Bruneton
- * @author Eugene Kuleshov
- */
-class ClassReader {
-    /**
-     * Pseudo access flag to distinguish between the synthetic attribute and the
-     * synthetic access flag.
-     */
-    static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
-
-
-    /**
-     * The type of CONSTANT_Class constant pool items.
-     */
-    static final int CLASS = 7;
-
-    /**
-     * The type of CONSTANT_Fieldref constant pool items.
-     */
-    static final int FIELD = 9;
-
-    /**
-     * The type of CONSTANT_Methodref constant pool items.
-     */
-    static final int METH = 10;
-
-    /**
-     * The type of CONSTANT_InterfaceMethodref constant pool items.
-     */
-    static final int IMETH = 11;
-
-    /**
-     * The type of CONSTANT_String constant pool items.
-     */
-    static final int STR = 8;
-
-    /**
-     * The type of CONSTANT_Integer constant pool items.
-     */
-    static final int INT = 3;
-
-    /**
-     * The type of CONSTANT_Float constant pool items.
-     */
-    static final int FLOAT = 4;
-
-    /**
-     * The type of CONSTANT_Long constant pool items.
-     */
-    static final int LONG = 5;
-
-    /**
-     * The type of CONSTANT_Double constant pool items.
-     */
-    static final int DOUBLE = 6;
-
-    /**
-     * The type of CONSTANT_NameAndType constant pool items.
-     */
-    static final int NAME_TYPE = 12;
-
-    /**
-     * The type of CONSTANT_Utf8 constant pool items.
-     */
-    static final int UTF8 = 1;
-
-    /**
-     * The type of CONSTANT_MethodType constant pool items.
-     */
-    static final int MTYPE = 16;
-
-    /**
-     * The type of CONSTANT_MethodHandle constant pool items.
-     */
-    static final int HANDLE = 15;
-
-    /**
-     * The type of CONSTANT_InvokeDynamic constant pool items.
-     */
-    static final int INDY = 18;
-
-    /**
-     * True to enable signatures support.
-     */
-    static final boolean SIGNATURES = true;
-
-    /**
-     * True to enable annotations support.
-     */
-    static final boolean ANNOTATIONS = true;
-
-
-    /**
-     * Flag to skip the debug information in the class. If this flag is set the
-     * debug information of the class is not visited, i.e. the
-     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
-     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
-     * called.
-     */
-    public static final int SKIP_DEBUG = 2;
-
-    /**
-     * The class to be parsed. <i>The content of this array must not be
-     * modified. This field is intended for {@link Attribute} sub classes, and
-     * is normally not needed by class generators or adapters.</i>
-     */
-    public final byte[] b;
-
-    /**
-     * The start index of each constant pool item in {@link #b b}, plus one. The
-     * one byte offset skips the constant pool item tag that indicates its type.
-     */
-    private final int[] items;
-
-    /**
-     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
-     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
-     * which GREATLY improves performances (by a factor 2 to 3). This caching
-     * strategy could be extended to all constant pool items, but its benefit
-     * would not be so great for these items (because they are much less
-     * expensive to parse than CONSTANT_Utf8 items).
-     */
-    private final String[] strings;
-
-    /**
-     * Maximum length of the strings contained in the constant pool of the
-     * class.
-     */
-    private final int maxStringLength;
-
-    /**
-     * Start index of the class header information (access, name...) in
-     * {@link #b b}.
-     */
-    public final int header;
-
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param b
-     *            the bytecode of the class to be read.
-     */
-    private ClassReader(final byte[] b) {
-        this(b, 0, b.length);
-    }
-
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param b
-     *            the bytecode of the class to be read.
-     * @param off
-     *            the start offset of the class data.
-     * @param len
-     *            the length of the class data.
-     */
-    public ClassReader(final byte[] b, final int off, final int len) {
-        this.b = b;
-        // checks the class version
-		/* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9
-        if (readShort(off + 6) > Opcodes.V1_8) {
-            throw new IllegalArgumentException();
-        }
-		*/
-        // parses the constant pool
-        items = new int[readUnsignedShort(off + 8)];
-        int n = items.length;
-        strings = new String[n];
-        int max = 0;
-        int index = off + 10;
-        for (int i = 1; i < n; ++i) {
-            items[i] = index + 1;
-            int size;
-            switch (b[index]) {
-                case FIELD:
-                case METH:
-                case IMETH:
-                case INT:
-                case FLOAT:
-                case NAME_TYPE:
-                case INDY:
-                    size = 5;
-                    break;
-                case LONG:
-                case DOUBLE:
-                    size = 9;
-                    ++i;
-                    break;
-                case UTF8:
-                    size = 3 + readUnsignedShort(index + 1);
-                    if (size > max) {
-                        max = size;
-                    }
-                    break;
-                case HANDLE:
-                    size = 4;
-                    break;
-                // case ClassWriter.CLASS:
-                // case ClassWriter.STR:
-                // case ClassWriter.MTYPE
-                default:
-                    size = 3;
-                    break;
-            }
-            index += size;
-        }
-        maxStringLength = max;
-        // the class header information starts just after the constant pool
-        header = index;
-    }
-
-    /**
-     * Returns the class's access flags (see {@link Opcodes}). This value may
-     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
-     * and those flags are represented by attributes.
-     *
-     * @return the class access flags
-     *
-     * @see ClassVisitor#visit(int, int, String, String, String, String[])
-     */
-    public int getAccess() {
-        return readUnsignedShort(header);
-    }
-
-    /**
-     * Returns the internal name of the class (see
-     * {@link Type#getInternalName() getInternalName}).
-     *
-     * @return the internal class name
-     *
-     * @see ClassVisitor#visit(int, int, String, String, String, String[])
-     */
-    public String getClassName() {
-        return readClass(header + 2, new char[maxStringLength]);
-    }
-
-    /**
-     * Returns the internal of name of the super class (see
-     * {@link Type#getInternalName() getInternalName}). For interfaces, the
-     * super class is {@link Object}.
-     *
-     * @return the internal name of super class, or <tt>null</tt> for
-     *         {@link Object} class.
-     *
-     * @see ClassVisitor#visit(int, int, String, String, String, String[])
-     */
-    public String getSuperName() {
-        return readClass(header + 4, new char[maxStringLength]);
-    }
-
-    /**
-     * Returns the internal names of the class's interfaces (see
-     * {@link Type#getInternalName() getInternalName}).
-     *
-     * @return the array of internal names for all implemented interfaces or
-     *         <tt>null</tt>.
-     *
-     * @see ClassVisitor#visit(int, int, String, String, String, String[])
-     */
-    public String[] getInterfaces() {
-        int index = header + 6;
-        int n = readUnsignedShort(index);
-        String[] interfaces = new String[n];
-        if (n > 0) {
-            char[] buf = new char[maxStringLength];
-            for (int i = 0; i < n; ++i) {
-                index += 2;
-                interfaces[i] = readClass(index, buf);
-            }
-        }
-        return interfaces;
-    }
-
-
-
-
-
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param is
-     *            an input stream from which to read the class.
-     * @throws IOException
-     *             if a problem occurs during reading.
-     */
-    public ClassReader(final InputStream is) throws IOException {
-        this(readClass(is, false));
-    }
-
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param name
-     *            the binary qualified name of the class to be read.
-     * @throws IOException
-     *             if an exception occurs during reading.
-     */
-    public ClassReader(final String name) throws IOException {
-        this(readClass(
-                ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
-                        + ".class"), true));
-    }
-
-    /**
-     * Reads the bytecode of a class.
-     *
-     * @param is
-     *            an input stream from which to read the class.
-     * @param close
-     *            true to close the input stream after reading.
-     * @return the bytecode read from the given input stream.
-     * @throws IOException
-     *             if a problem occurs during reading.
-     */
-    private static byte[] readClass(final InputStream is, boolean close)
-            throws IOException {
-        if (is == null) {
-            throw new IOException("Class not found");
-        }
-        try {
-            byte[] b = new byte[is.available()];
-            int len = 0;
-            while (true) {
-                int n = is.read(b, len, b.length - len);
-                if (n == -1) {
-                    if (len < b.length) {
-                        byte[] c = new byte[len];
-                        System.arraycopy(b, 0, c, 0, len);
-                        b = c;
-                    }
-                    return b;
-                }
-                len += n;
-                if (len == b.length) {
-                    int last = is.read();
-                    if (last < 0) {
-                        return b;
-                    }
-                    byte[] c = new byte[b.length + 1000];
-                    System.arraycopy(b, 0, c, 0, len);
-                    c[len++] = (byte) last;
-                    b = c;
-                }
-            }
-        } finally {
-            if (close) {
-                is.close();
-            }
-        }
-    }
-
-    // ------------------------------------------------------------------------
-    // Public methods
-    // ------------------------------------------------------------------------
-
-    /**
-     * Makes the given visitor visit the Java class of this {@link ClassReader}
-     * . This class is the one specified in the constructor (see
-     * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor
-     *            the visitor that must visit this class.
-     */
-    public void accept(final ClassVisitor classVisitor, final int flags) {
-        accept(classVisitor, new Attribute[0], flags);
-    }
-
-    /**
-     * Makes the given visitor visit the Java class of this {@link ClassReader}.
-     * This class is the one specified in the constructor (see
-     * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor
-     *            the visitor that must visit this class.
-     * @param attrs
-     *            prototypes of the attributes that must be parsed during the
-     *            visit of the class. Any attribute whose type is not equal to
-     *            the type of one the prototypes will not be parsed: its byte
-     *            array value will be passed unchanged to the ClassWriter.
-     *            <i>This may corrupt it if this value contains references to
-     *            the constant pool, or has syntactic or semantic links with a
-     *            class element that has been transformed by a class adapter
-     *            between the reader and the writer</i>.
-     */
-    public void accept(final ClassVisitor classVisitor,
-                       final Attribute[] attrs, final int flags) {
-        int u = header; // current offset in the class file
-        char[] c = new char[maxStringLength]; // buffer used to read strings
-
-        Context context = new Context();
-        context.attrs = attrs;
-        context.flags = flags;
-        context.buffer = c;
-
-        // reads the class declaration
-        int access = readUnsignedShort(u);
-        String name = readClass(u + 2, c);
-        String superClass = readClass(u + 4, c);
-        String[] interfaces = new String[readUnsignedShort(u + 6)];
-        u += 8;
-        for (int i = 0; i < interfaces.length; ++i) {
-            interfaces[i] = readClass(u, c);
-            u += 2;
-        }
-
-        // reads the class attributes
-        String signature = null;
-        String sourceFile = null;
-        String sourceDebug = null;
-        String enclosingOwner = null;
-        String enclosingName = null;
-        String enclosingDesc = null;
-        int anns = 0;
-        int ianns = 0;
-        int tanns = 0;
-        int itanns = 0;
-        int innerClasses = 0;
-        Attribute attributes = null;
-
-        u = getAttributes();
-        for (int i = readUnsignedShort(u); i > 0; --i) {
-            String attrName = readUTF8(u + 2, c);
-            // tests are sorted in decreasing frequency order
-            // (based on frequencies observed on typical classes)
-            if ("SourceFile".equals(attrName)) {
-                sourceFile = readUTF8(u + 8, c);
-            } else if ("InnerClasses".equals(attrName)) {
-                innerClasses = u + 8;
-            } else if ("EnclosingMethod".equals(attrName)) {
-                enclosingOwner = readClass(u + 8, c);
-                int item = readUnsignedShort(u + 10);
-                if (item != 0) {
-                    enclosingName = readUTF8(items[item], c);
-                    enclosingDesc = readUTF8(items[item] + 2, c);
-                }
-            } else if (SIGNATURES && "Signature".equals(attrName)) {
-                signature = readUTF8(u + 8, c);
-            } else if (ANNOTATIONS
-                    && "RuntimeVisibleAnnotations".equals(attrName)) {
-                anns = u + 8;
-            } else if (ANNOTATIONS
-                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
-                tanns = u + 8;
-            } else if ("Deprecated".equals(attrName)) {
-                access |= Opcodes.ACC_DEPRECATED;
-            } else if ("Synthetic".equals(attrName)) {
-                access |= Opcodes.ACC_SYNTHETIC
-                        | ACC_SYNTHETIC_ATTRIBUTE;
-            } else if ("SourceDebugExtension".equals(attrName)) {
-                int len = readInt(u + 4);
-                sourceDebug = readUTF(u + 8, len, new char[len]);
-            } else if (ANNOTATIONS
-                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                ianns = u + 8;
-            } else if (ANNOTATIONS
-                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
-                itanns = u + 8;
-            } else if ("BootstrapMethods".equals(attrName)) {
-                int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
-                for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
-                    bootstrapMethods[j] = v;
-                    v += 2 + readUnsignedShort(v + 2) << 1;
-                }
-                context.bootstrapMethods = bootstrapMethods;
-            } else {
-                Attribute attr = readAttribute(attrs, attrName, u + 8,
-                        readInt(u + 4), c, -1, null);
-                if (attr != null) {
-                    attr.next = attributes;
-                    attributes = attr;
-                }
-            }
-            u += 6 + readInt(u + 4);
-        }
-
-        // visits the class declaration
-        classVisitor.visit(readInt(items[1] - 7), access, name, signature,
-                superClass, interfaces);
-
-        // visits the source and debug info
-        if ((flags & SKIP_DEBUG) == 0
-                && (sourceFile != null || sourceDebug != null)) {
-            classVisitor.visitSource(sourceFile, sourceDebug);
-        }
-
-        // visits the outer class
-        if (enclosingOwner != null) {
-            classVisitor.visitOuterClass(enclosingOwner, enclosingName,
-                    enclosingDesc);
-        }
-
-        // visits the class annotations and type annotations
-        if (ANNOTATIONS && anns != 0) {
-            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
-                v = readAnnotationValues(v + 2, c, true,
-                        classVisitor.visitAnnotation(readUTF8(v, c), true));
-            }
-        }
-        if (ANNOTATIONS && ianns != 0) {
-            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
-                v = readAnnotationValues(v + 2, c, true,
-                        classVisitor.visitAnnotation(readUTF8(v, c), false));
-            }
-        }
-
-        // visits the end of the class
-        classVisitor.visitEnd();
-    }
-
-    /**
-     * Reads the values of an annotation and makes the given visitor visit them.
-     *
-     * @param v
-     *            the start offset in {@link #b b} of the values to be read
-     *            (including the unsigned short that gives the number of
-     *            values).
-     * @param buf
-     *            buffer to be used to call {@link #readUTF8 readUTF8},
-     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
-     *            readConst}.
-     * @param named
-     *            if the annotation values are named or not.
-     * @param av
-     *            the visitor that must visit the values.
-     * @return the end offset of the annotation values.
-     */
-    private int readAnnotationValues(int v, final char[] buf,
-                                     final boolean named, final AnnotationVisitor av) {
-        int i = readUnsignedShort(v);
-        v += 2;
-        if (named) {
-            for (; i > 0; --i) {
-                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
-            }
-        } else {
-            for (; i > 0; --i) {
-                v = readAnnotationValue(v, buf, null, av);
-            }
-        }
-        if (av != null) {
-            av.visitEnd();
-        }
-        return v;
-    }
-
-    /**
-     * Reads a value of an annotation and makes the given visitor visit it.
-     *
-     * @param v
-     *            the start offset in {@link #b b} of the value to be read
-     *            (<i>not including the value name constant pool index</i>).
-     * @param buf
-     *            buffer to be used to call {@link #readUTF8 readUTF8},
-     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
-     *            readConst}.
-     * @param name
-     *            the name of the value to be read.
-     * @param av
-     *            the visitor that must visit the value.
-     * @return the end offset of the annotation value.
-     */
-    private int readAnnotationValue(int v, final char[] buf, final String name,
-                                    final AnnotationVisitor av) {
-        int i;
-        if (av == null) {
-            switch (b[v] & 0xFF) {
-                case 'e': // enum_const_value
-                    return v + 5;
-                case '@': // annotation_value
-                    return readAnnotationValues(v + 3, buf, true, null);
-                case '[': // array_value
-                    return readAnnotationValues(v + 1, buf, false, null);
-                default:
-                    return v + 3;
-            }
-        }
-        switch (b[v++] & 0xFF) {
-            case 'I': // pointer to CONSTANT_Integer
-            case 'J': // pointer to CONSTANT_Long
-            case 'F': // pointer to CONSTANT_Float
-            case 'D': // pointer to CONSTANT_Double
-                av.visit(name, readConst(readUnsignedShort(v), buf));
-                v += 2;
-                break;
-            case 'B': // pointer to CONSTANT_Byte
-                av.visit(name, (byte) readInt(items[readUnsignedShort(v)]));
-                v += 2;
-                break;
-            case 'Z': // pointer to CONSTANT_Boolean
-                av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE : Boolean.TRUE);
-                v += 2;
-                break;
-            case 'S': // pointer to CONSTANT_Short
-                av.visit(name, (short) readInt(items[readUnsignedShort(v)]));
-                v += 2;
-                break;
-            case 'C': // pointer to CONSTANT_Char
-                av.visit(name, (char) readInt(items[readUnsignedShort(v)]));
-                v += 2;
-                break;
-            case 's': // pointer to CONSTANT_Utf8
-                av.visit(name, readUTF8(v, buf));
-                v += 2;
-                break;
-            case 'e': // enum_const_value
-                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
-                v += 4;
-                break;
-            case 'c': // class_info
-                av.visit(name, Type.getType(readUTF8(v, buf)));
-                v += 2;
-                break;
-            case '@': // annotation_value
-                v = readAnnotationValues(v + 2, buf, true,
-                        av.visitAnnotation(name, readUTF8(v, buf)));
-                break;
-            case '[': // array_value
-                int size = readUnsignedShort(v);
-                v += 2;
-                if (size == 0) {
-                    return readAnnotationValues(v - 2, buf, false,
-                            av.visitArray(name));
-                }
-                switch (this.b[v++] & 0xFF) {
-                    case 'B':
-                        byte[] bv = new byte[size];
-                        for (i = 0; i < size; i++) {
-                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
-                            v += 3;
-                        }
-                        av.visit(name, bv);
-                        --v;
-                        break;
-                    case 'Z':
-                        boolean[] zv = new boolean[size];
-                        for (i = 0; i < size; i++) {
-                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
-                            v += 3;
-                        }
-                        av.visit(name, zv);
-                        --v;
-                        break;
-                    case 'S':
-                        short[] sv = new short[size];
-                        for (i = 0; i < size; i++) {
-                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
-                            v += 3;
-                        }
-                        av.visit(name, sv);
-                        --v;
-                        break;
-                    case 'C':
-                        char[] cv = new char[size];
-                        for (i = 0; i < size; i++) {
-                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
-                            v += 3;
-                        }
-                        av.visit(name, cv);
-                        --v;
-                        break;
-                    case 'I':
-                        int[] iv = new int[size];
-                        for (i = 0; i < size; i++) {
-                            iv[i] = readInt(items[readUnsignedShort(v)]);
-                            v += 3;
-                        }
-                        av.visit(name, iv);
-                        --v;
-                        break;
-                    case 'J':
-                        long[] lv = new long[size];
-                        for (i = 0; i < size; i++) {
-                            lv[i] = readLong(items[readUnsignedShort(v)]);
-                            v += 3;
-                        }
-                        av.visit(name, lv);
-                        --v;
-                        break;
-                    case 'F':
-                        float[] fv = new float[size];
-                        for (i = 0; i < size; i++) {
-                            fv[i] = Float
-                                    .intBitsToFloat(readInt(items[readUnsignedShort(v)]));
-                            v += 3;
-                        }
-                        av.visit(name, fv);
-                        --v;
-                        break;
-                    case 'D':
-                        double[] dv = new double[size];
-                        for (i = 0; i < size; i++) {
-                            dv[i] = Double
-                                    .longBitsToDouble(readLong(items[readUnsignedShort(v)]));
-                            v += 3;
-                        }
-                        av.visit(name, dv);
-                        --v;
-                        break;
-                    default:
-                        v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
-                }
-        }
-        return v;
-    }
-
-
-    /**
-     * Returns the label corresponding to the given offset. The default
-     * implementation of this method creates a label for the given offset if it
-     * has not been already created.
-     *
-     * @param offset
-     *            a bytecode offset in a method.
-     * @param labels
-     *            the already created labels, indexed by their offset. If a
-     *            label already exists for offset this method must not create a
-     *            new one. Otherwise it must store the new label in this array.
-     * @return a non null Label, which must be equal to labels[offset].
-     */
-    protected Label readLabel(int offset, Label[] labels) {
-        // SPRING PATCH: leniently handle offset mismatch
-        if (offset >= labels.length) {
-            return new Label();
-        }
-        // END OF PATCH
-        if (labels[offset] == null) {
-            labels[offset] = new Label();
-        }
-        return labels[offset];
-    }
-
-    /**
-     * Returns the start index of the attribute_info structure of this class.
-     *
-     * @return the start index of the attribute_info structure of this class.
-     */
-    private int getAttributes() {
-        // skips the header
-        int u = header + 8 + readUnsignedShort(header + 6) * 2;
-        // skips fields and methods
-        for (int i = readUnsignedShort(u); i > 0; --i) {
-            for (int j = readUnsignedShort(u + 8); j > 0; --j) {
-                u += 6 + readInt(u + 12);
-            }
-            u += 8;
-        }
-        u += 2;
-        for (int i = readUnsignedShort(u); i > 0; --i) {
-            for (int j = readUnsignedShort(u + 8); j > 0; --j) {
-                u += 6 + readInt(u + 12);
-            }
-            u += 8;
-        }
-        // the attribute_info structure starts just after the methods
-        return u + 2;
-    }
-
-    /**
-     * Reads an attribute in {@link #b b}.
-     *
-     * @param attrs
-     *            prototypes of the attributes that must be parsed during the
-     *            visit of the class. Any attribute whose type is not equal to
-     *            the type of one the prototypes is ignored (i.e. an empty
-     *            {@link Attribute} instance is returned).
-     * @param type
-     *            the type of the attribute.
-     * @param off
-     *            index of the first byte of the attribute's content in
-     *            {@link #b b}. The 6 attribute header bytes, containing the
-     *            type and the length of the attribute, are not taken into
-     *            account here (they have already been read).
-     * @param len
-     *            the length of the attribute's content.
-     * @param buf
-     *            buffer to be used to call {@link #readUTF8 readUTF8},
-     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
-     *            readConst}.
-     * @param codeOff
-     *            index of the first byte of code's attribute content in
-     *            {@link #b b}, or -1 if the attribute to be read is not a code
-     *            attribute. The 6 attribute header bytes, containing the type
-     *            and the length of the attribute, are not taken into account
-     *            here.
-     * @param labels
-     *            the labels of the method's code, or <tt>null</tt> if the
-     *            attribute to be read is not a code attribute.
-     * @return the attribute that has been read, or <tt>null</tt> to skip this
-     *         attribute.
-     */
-    private Attribute readAttribute(final Attribute[] attrs, final String type,
-                                    final int off, final int len, final char[] buf, final int codeOff,
-                                    final Label[] labels) {
-        for (int i = 0; i < attrs.length; ++i) {
-            if (attrs[i].type.equals(type)) {
-                return attrs[i].read(this, off, len, buf, codeOff, labels);
-            }
-        }
-        return new Attribute(type).read(this, off, len, null, -1, null);
-    }
-
-
-    /**
-     * Reads a byte value in {@link #b b}. <i>This method is intended for
-     * {@link Attribute} sub classes, and is normally not needed by class
-     * generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of the value to be read in {@link #b b}.
-     * @return the read value.
-     */
-    public int readByte(final int index) {
-        return b[index] & 0xFF;
-    }
-
-    /**
-     * Reads an unsigned short value in {@link #b b}. <i>This method is intended
-     * for {@link Attribute} sub classes, and is normally not needed by class
-     * generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of the value to be read in {@link #b b}.
-     * @return the read value.
-     */
-    public int readUnsignedShort(final int index) {
-        byte[] b = this.b;
-        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
-    }
-
-    /**
-     * Reads a signed short value in {@link #b b}. <i>This method is intended
-     * for {@link Attribute} sub classes, and is normally not needed by class
-     * generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of the value to be read in {@link #b b}.
-     * @return the read value.
-     */
-    public short readShort(final int index) {
-        byte[] b = this.b;
-        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
-    }
-
-    /**
-     * Reads a signed int value in {@link #b b}. <i>This method is intended for
-     * {@link Attribute} sub classes, and is normally not needed by class
-     * generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of the value to be read in {@link #b b}.
-     * @return the read value.
-     */
-    public int readInt(final int index) {
-        byte[] b = this.b;
-        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
-                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
-    }
-
-    /**
-     * Reads a signed long value in {@link #b b}. <i>This method is intended for
-     * {@link Attribute} sub classes, and is normally not needed by class
-     * generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of the value to be read in {@link #b b}.
-     * @return the read value.
-     */
-    public long readLong(final int index) {
-        long l1 = readInt(index);
-        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
-        return (l1 << 32) | l0;
-    }
-
-    /**
-     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
-     * is intended for {@link Attribute} sub classes, and is normally not needed
-     * by class generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of an unsigned short value in {@link #b b},
-     *            whose value is the index of an UTF8 constant pool item.
-     * @param buf
-     *            buffer to be used to read the item. This buffer must be
-     *            sufficiently large. It is not automatically resized.
-     * @return the String corresponding to the specified UTF8 item.
-     */
-    public String readUTF8(int index, final char[] buf) {
-        int item = readUnsignedShort(index);
-        if (index == 0 || item == 0) {
-            return null;
-        }
-        String s = strings[item];
-        if (s != null) {
-            return s;
-        }
-        index = items[item];
-        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
-    }
-
-    /**
-     * Reads UTF8 string in {@link #b b}.
-     *
-     * @param index
-     *            start offset of the UTF8 string to be read.
-     * @param utfLen
-     *            length of the UTF8 string to be read.
-     * @param buf
-     *            buffer to be used to read the string. This buffer must be
-     *            sufficiently large. It is not automatically resized.
-     * @return the String corresponding to the specified UTF8 string.
-     */
-    private String readUTF(int index, final int utfLen, final char[] buf) {
-        int endIndex = index + utfLen;
-        byte[] b = this.b;
-        int strLen = 0;
-        int c;
-        int st = 0;
-        char cc = 0;
-        while (index < endIndex) {
-            c = b[index++];
-            switch (st) {
-                case 0:
-                    c = c & 0xFF;
-                    if (c < 0x80) { // 0xxxxxxx
-                        buf[strLen++] = (char) c;
-                    } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
-                        cc = (char) (c & 0x1F);
-                        st = 1;
-                    } else { // 1110 xxxx 10xx xxxx 10xx xxxx
-                        cc = (char) (c & 0x0F);
-                        st = 2;
-                    }
-                    break;
-
-                case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
-                    buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
-                    st = 0;
-                    break;
-
-                case 2: // byte 2 of 3-byte char
-                    cc = (char) ((cc << 6) | (c & 0x3F));
-                    st = 1;
-                    break;
-            }
-        }
-        return new String(buf, 0, strLen);
-    }
-
-    /**
-     * Reads a class constant pool item in {@link #b b}. <i>This method is
-     * intended for {@link Attribute} sub classes, and is normally not needed by
-     * class generators or adapters.</i>
-     *
-     * @param index
-     *            the start index of an unsigned short value in {@link #b b},
-     *            whose value is the index of a class constant pool item.
-     * @param buf
-     *            buffer to be used to read the item. This buffer must be
-     *            sufficiently large. It is not automatically resized.
-     * @return the String corresponding to the specified class item.
-     */
-    public String readClass(final int index, final char[] buf) {
-        // computes the start index of the CONSTANT_Class item in b
-        // and reads the CONSTANT_Utf8 item designated by
-        // the first two bytes of this CONSTANT_Class item
-        return readUTF8(items[readUnsignedShort(index)], buf);
-    }
-
-    /**
-     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
-     * method is intended for {@link Attribute} sub classes, and is normally not
-     * needed by class generators or adapters.</i>
-     *
-     * @param item
-     *            the index of a constant pool item.
-     * @param buf
-     *            buffer to be used to read the item. This buffer must be
-     *            sufficiently large. It is not automatically resized.
-     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
-     *         {@link String}, {@link Type} or {@link Handle} corresponding to
-     *         the given constant pool item.
-     */
-    public Object readConst(final int item, final char[] buf) {
-        int index = items[item];
-        switch (b[index - 1]) {
-            case INT:
-                return readInt(index);
-            case FLOAT:
-                return Float.intBitsToFloat(readInt(index));
-            case LONG:
-                return readLong(index);
-            case DOUBLE:
-                return Double.longBitsToDouble(readLong(index));
-            case CLASS:
-                return Type.getObjectType(readUTF8(index, buf));
-            case STR:
-                return readUTF8(index, buf);
-            case MTYPE:
-                return Type.getMethodType(readUTF8(index, buf));
-            default: // case ClassWriter.HANDLE_BASE + [1..9]:
-                int tag = readByte(index);
-                int[] items = this.items;
-                int cpIndex = items[readUnsignedShort(index + 1)];
-                String owner = readClass(cpIndex, buf);
-                cpIndex = items[readUnsignedShort(cpIndex + 2)];
-                String name = readUTF8(cpIndex, buf);
-                String desc = readUTF8(cpIndex + 2, buf);
-                return new Handle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
-        }
-    }
-}
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java
deleted file mode 100644
index 2ad9692aa0..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.grails.common.compiler.asm;
-
-import org.springframework.asm.Label;
-
-/**
- * Information about a class being parsed in a {@link ClassReader}.
- *
- * @author Eric Bruneton
- */
-class Context {
-
-    /**
-     * Prototypes of the attributes that must be parsed for this class.
-     */
-    Attribute[] attrs;
-
-    /**
-     * The {@link ClassReader} option flags for the parsing of this class.
-     */
-    int flags;
-
-    /**
-     * The buffer used to read strings.
-     */
-    char[] buffer;
-
-    /**
-     * The start index of each bootstrap method.
-     */
-    int[] bootstrapMethods;
-
-    /**
-     * The access flags of the method currently being parsed.
-     */
-    int access;
-
-    /**
-     * The name of the method currently being parsed.
-     */
-    String name;
-
-    /**
-     * The descriptor of the method currently being parsed.
-     */
-    String desc;
-
-    /**
-     * The label objects, indexed by bytecode offset, of the method currently
-     * being parsed (only bytecode offsets for which a label is needed have a
-     * non null associated Label object).
-     */
-    Label[] labels;
-
-    /**
-     * The target of the type annotation currently being parsed.
-     */
-    int typeRef;
-
-    /**
-     * The path of the type annotation currently being parsed.
-     */
-    TypePath typePath;
-
-    /**
-     * The offset of the latest stack map frame that has been parsed.
-     */
-    int offset;
-
-    /**
-     * The labels corresponding to the start of the local variable ranges in the
-     * local variable type annotation currently being parsed.
-     */
-    Label[] start;
-
-    /**
-     * The labels corresponding to the end of the local variable ranges in the
-     * local variable type annotation currently being parsed.
-     */
-    Label[] end;
-
-    /**
-     * The local variable indices for each local variable range in the local
-     * variable type annotation currently being parsed.
-     */
-    int[] index;
-
-    /**
-     * The encoding of the latest stack map frame that has been parsed.
-     */
-    int mode;
-
-    /**
-     * The number of locals in the latest stack map frame that has been parsed.
-     */
-    int localCount;
-
-    /**
-     * The number locals in the latest stack map frame that has been parsed,
-     * minus the number of locals in the previous frame.
-     */
-    int localDiff;
-
-    /**
-     * The local values of the latest stack map frame that has been parsed.
-     */
-    Object[] local;
-
-    /**
-     * The stack size of the latest stack map frame that has been parsed.
-     */
-    int stackCount;
-
-    /**
-     * The stack values of the latest stack map frame that has been parsed.
-     */
-    Object[] stack;
-}
\ No newline at end of file
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java
deleted file mode 100644
index f2510b12aa..0000000000
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.grails.common.compiler.asm;
-
-
-/**
- * The path to a type argument, wildcard bound, array element type, or static
- * inner type within an enclosing type.
- *
- * @author Eric Bruneton
- */
-class TypePath {
-
-    /**
-     * A type path step that steps into the element type of an array type. See
-     * {@link #getStep getStep}.
-     */
-    public final static int ARRAY_ELEMENT = 0;
-
-    /**
-     * A type path step that steps into the nested type of a class type. See
-     * {@link #getStep getStep}.
-     */
-    public final static int INNER_TYPE = 1;
-
-    /**
-     * A type path step that steps into the bound of a wildcard type. See
-     * {@link #getStep getStep}.
-     */
-    public final static int WILDCARD_BOUND = 2;
-
-    /**
-     * A type path step that steps into a type argument of a generic type. See
-     * {@link #getStep getStep}.
-     */
-    public final static int TYPE_ARGUMENT = 3;
-
-    /**
-     * The byte array where the path is stored, in Java class file format.
-     */
-    byte[] b;
-
-    /**
-     * The offset of the first byte of the type path in 'b'.
-     */
-    int offset;
-
-    /**
-     * Creates a new type path.
-     *
-     * @param b
-     *            the byte array containing the type path in Java class file
-     *            format.
-     * @param offset
-     *            the offset of the first byte of the type path in 'b'.
-     */
-    TypePath(byte[] b, int offset) {
-        this.b = b;
-        this.offset = offset;
-    }
-
-    /**
-     * Returns the length of this path.
-     *
-     * @return the length of this path.
-     */
-    public int getLength() {
-        return b[offset];
-    }
-
-    /**
-     * Returns the value of the given step of this path.
-     *
-     * @param index
-     *            an index between 0 and {@link #getLength()}, exclusive.
-     * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
-     *         INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
-     *         {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
-     */
-    public int getStep(int index) {
-        return b[offset + 2 * index + 1];
-    }
-
-    /**
-     * Returns the index of the type argument that the given step is stepping
-     * into. This method should only be used for steps whose value is
-     * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
-     *
-     * @param index
-     *            an index between 0 and {@link #getLength()}, exclusive.
-     * @return the index of the type argument that the given step is stepping
-     *         into.
-     */
-    public int getStepArgument(int index) {
-        return b[offset + 2 * index + 2];
-    }
-
-    /**
-     * Converts a type path in string form, in the format used by
-     * {@link #toString()}, into a TypePath object.
-     *
-     * @param typePath
-     *            a type path in string form, in the format used by
-     *            {@link #toString()}. May be null or empty.
-     * @return the corresponding TypePath object, or null if the path is empty.
-     */
-    public static TypePath fromString(final String typePath) {
-        if (typePath == null || typePath.length() == 0) {
-            return null;
-        }
-        int n = typePath.length();
-        ByteVector out = new ByteVector(n);
-        out.putByte(0);
-        for (int i = 0; i < n;) {
-            char c = typePath.charAt(i++);
-            if (c == '[') {
-                out.put11(ARRAY_ELEMENT, 0);
-            } else if (c == '.') {
-                out.put11(INNER_TYPE, 0);
-            } else if (c == '*') {
-                out.put11(WILDCARD_BOUND, 0);
-            } else if (c >= '0' && c <= '9') {
-                int typeArg = c - '0';
-                while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
-                    typeArg = typeArg * 10 + c - '0';
-                    i += 1;
-                }
-                if (i < n && typePath.charAt(i) == ';') {
-                    i += 1;
-                }
-                out.put11(TYPE_ARGUMENT, typeArg);
-            }
-        }
-        out.data[0] = (byte) (out.length / 2);
-        return new TypePath(out.data, 0);
-    }
-
-    /**
-     * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
-     * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
-     * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
-     * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
-     * argument index in decimal form followed by ';'.
-     */
-    @Override
-    public String toString() {
-        int length = getLength();
-        StringBuilder result = new StringBuilder(length * 2);
-        for (int i = 0; i < length; ++i) {
-            switch (getStep(i)) {
-                case ARRAY_ELEMENT:
-                    result.append('[');
-                    break;
-                case INNER_TYPE:
-                    result.append('.');
-                    break;
-                case WILDCARD_BOUND:
-                    result.append('*');
-                    break;
-                case TYPE_ARGUMENT:
-                    result.append(getStepArgument(i)).append(';');
-                    break;
-                default:
-                    result.append('_');
-            }
-        }
-        return result.toString();
-    }
-}
diff --git a/grails-common/src/main/resources/META-INF/LICENSE b/grails-common/src/main/resources/META-INF/LICENSE
deleted file mode 100644
index 9f2db4a21e..0000000000
--- a/grails-common/src/main/resources/META-INF/LICENSE
+++ /dev/null
@@ -1,233 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       https://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
---------------------------------------------------------------------------
-
-BSD License
-
-The following classes within this product:
-
-    org.apache.grails.common.compiler.asm.Attribute
-    org.apache.grails.common.compiler.asm.ByteVector
-    org.apache.grails.common.compiler.asm.ClassReader
-    org.apache.grails.common.compiler.asm.Context
-    org.apache.grails.common.compiler.asm.TypePath
-
-See the LICENSE/licenses-asm.txt file for the ASM license terms.
-
---------------------------------------------------------------------------
-
-This product includes the following classes from Spring Framework 5.3, developed by Pivotal Software, Inc., licensed under the Apache License 2.0:
-
-    org.apache.grails.common.annotation.AbstractRecursiveAnnotationVisitor
-    org.apache.grails.common.annotation.AnnotationAttributesReadingVisitor
-    org.apache.grails.common.annotation.AnnotationMetadataReadingVisitor
-    org.apache.grails.common.annotation.AnnotationReadingVisitorUtils
-    org.apache.grails.common.annotation.ClassMetadataReadingVisitor
-    org.apache.grails.common.annotation.MethodMetadataReadingVisitor
-    org.apache.grails.common.annotation.RecursiveAnnotationArrayVisitor
-    org.apache.grails.common.annotation.RecursiveAnnotationAttributesVisitor
-
-See the above Apache License 2.0 for the terms governing these files.
-
---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/grails-common/src/main/resources/META-INF/NOTICE b/grails-common/src/main/resources/META-INF/NOTICE
deleted file mode 100644
index d524ab7e3e..0000000000
--- a/grails-common/src/main/resources/META-INF/NOTICE
+++ /dev/null
@@ -1,18 +0,0 @@
-Apache Grails
-Copyright 2005-2025 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-
-Additional Licenses
-------------------
-
-ASM Library
-This product includes software from ASM Library, licensed under BSD License.
-Copyright 2000-2011 INRIA, France Telecom.
-See licenses/LICENSE-asm.txt for the full license terms.
-
-This product includes software from Spring Framework 5.3, developed by Pivotal Software, Inc.
-Copyright 2002-2020 the original author or authors.
-See the LICENSE file for the Apache License 2.0 terms.
\ No newline at end of file
diff --git a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy
index 88fc29a66b..8691eaf698 100644
--- a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy
+++ b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy
@@ -22,11 +22,11 @@ import groovy.transform.CompileStatic
 import groovy.transform.InheritConstructors
 import groovy.transform.Memoized
 import groovy.util.logging.Slf4j
-import org.apache.grails.common.compiler.asm.AnnotationMetadataReader
 import org.springframework.core.io.DefaultResourceLoader
 import org.springframework.core.io.Resource
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver
 import org.springframework.core.io.support.ResourcePatternResolver
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory
 import org.springframework.util.ClassUtils
 
 import java.lang.annotation.Annotation
@@ -173,10 +173,12 @@ class ClassPathScanner {
 
     private void scanUsingPattern(ResourcePatternResolver resourcePatternResolver, String pattern, ClassLoader classLoader, Closure<Boolean> annotationFilter, Set<Class> classes) {
         def resources = resourcePatternResolver.getResources(pattern)
+
+        def factory = new SimpleMetadataReaderFactory(classLoader)
         for (Resource res in resources) {
             // ignore closures / inner classes
             if (!isExcluded(res)) {
-                def reader = new AnnotationMetadataReader(res, classLoader)
+                def reader = factory.getMetadataReader(res)
                 def metadata = reader.annotationMetadata
                 if (metadata.annotationTypes.any(annotationFilter)) {
                     classes << classLoader.loadClass(reader.classMetadata.className)
diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java
deleted file mode 100644
index 78b29ec529..0000000000
--- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.grails.datastore.gorm.utils;
-
-import org.apache.grails.common.compiler.asm.AnnotationMetadataReader;
-import org.springframework.core.io.Resource;
-import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
-import org.springframework.core.type.classreading.MetadataReader;
-
-import java.io.IOException;
-
-/**
- * A {@link CachingMetadataReaderFactory} that only reads annotations and not the whole class body
- */
-class AnnotationMetadataReaderFactory extends CachingMetadataReaderFactory {
-    public AnnotationMetadataReaderFactory(ClassLoader classLoader) {
-        super(classLoader);
-    }
-
-    @Override
-    public MetadataReader getMetadataReader(Resource resource) throws IOException {
-        return new AnnotationMetadataReader(resource, getResourceLoader().getClassLoader(), false);
-    }
-}
diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
index c39a25c10d..b180ea815d 100644
--- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
+++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
@@ -24,6 +24,7 @@ import groovy.util.logging.Slf4j
 import org.grails.datastore.mapping.reflect.ClassUtils
 import org.springframework.beans.factory.config.BeanDefinition
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory
 import org.springframework.core.type.filter.AnnotationTypeFilter
 
 import java.lang.annotation.Annotation
@@ -70,7 +71,7 @@ class ClasspathEntityScanner {
      */
     Class[] scan(Package... packages) {
         ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false)
-        componentProvider.setMetadataReaderFactory(new AnnotationMetadataReaderFactory(classLoader))
+        componentProvider.setMetadataReaderFactory(new SimpleMetadataReaderFactory(classLoader))
         for(ann in annotations) {
             componentProvider.addIncludeFilter(new AnnotationTypeFilter(ann))
         }
diff --git a/licenses/LICENSE-asm.txt b/licenses/LICENSE-asm.txt
deleted file mode 100644
index 1a71c4ce46..0000000000
--- a/licenses/LICENSE-asm.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-ASM: a very small and fast Java bytecode manipulation framework
-Copyright (c) 2000-2011 INRIA, France Telecom
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the copyright holders nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.