diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index d86baaac3621a..a70621f23998b 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -47,7 +47,6 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; import java.lang.reflect.RecordComponent; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -82,12 +81,11 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; +import sun.invoke.util.BytecodeDescriptor; import sun.invoke.util.Wrapper; import sun.reflect.generics.factory.CoreReflectionFactory; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.repository.ClassRepository; -import sun.reflect.generics.repository.MethodRepository; -import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.scope.ClassScope; import sun.reflect.annotation.*; @@ -1437,17 +1435,10 @@ public Method getEnclosingMethod() { if (!enclosingInfo.isMethod()) return null; - MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(), - getFactory()); - Class returnType = toClass(typeInfo.getReturnType()); - Type [] parameterTypes = typeInfo.getParameterTypes(); - Class[] parameterClasses = new Class[parameterTypes.length]; - - // Convert Types to Classes; returned types *should* - // be class objects since the methodDescriptor's used - // don't have generics information - for(int i = 0; i < parameterClasses.length; i++) - parameterClasses[i] = toClass(parameterTypes[i]); + // Descriptor already validated by VM + List> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader()); + Class returnType = types.removeLast(); + Class[] parameterClasses = types.toArray(EMPTY_CLASS_ARRAY); final Class enclosingCandidate = enclosingInfo.getEnclosingClass(); Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false); @@ -1566,17 +1557,10 @@ public Constructor getEnclosingConstructor() { if (!enclosingInfo.isConstructor()) return null; - ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(), - getFactory()); - Type [] parameterTypes = typeInfo.getParameterTypes(); - Class[] parameterClasses = new Class[parameterTypes.length]; - - // Convert Types to Classes; returned types *should* - // be class objects since the methodDescriptor's used - // don't have generics information - for (int i = 0; i < parameterClasses.length; i++) - parameterClasses[i] = toClass(parameterTypes[i]); - + // Descriptor already validated by VM + List> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader()); + types.removeLast(); + Class[] parameterClasses = types.toArray(EMPTY_CLASS_ARRAY); final Class enclosingCandidate = enclosingInfo.getEnclosingClass(); Constructor[] candidates = enclosingCandidate @@ -1882,7 +1866,7 @@ public Class[] getClasses() { } currentClass = currentClass.getSuperclass(); } - return list.toArray(new Class[0]); + return list.toArray(EMPTY_CLASS_ARRAY); } diff --git a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java index 53fd632275837..bf842bf33d70b 100644 --- a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java +++ b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,9 +37,26 @@ public class BytecodeDescriptor { private BytecodeDescriptor() { } // cannot instantiate + /** + * @throws IllegalArgumentException if the descriptor is invalid + * @throws TypeNotPresentException if the descriptor is valid, but + * the class cannot be found by the loader + */ + public static Class parseClass(String descriptor, ClassLoader loader) { + int[] i = {0}; + var ret = parseSig(descriptor, i, descriptor.length(), loader); + if (i[0] != descriptor.length() || ret == null) { + parseError("not a class descriptor", descriptor); + } + return ret; + } + /** * @param loader the class loader in which to look up the types (null means * bootstrap class loader) + * @throws IllegalArgumentException if the descriptor is invalid + * @throws TypeNotPresentException if the descriptor is valid, but + * a reference type cannot be found by the loader */ public static List> parseMethod(String bytecodeSignature, ClassLoader loader) { return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader); @@ -78,6 +95,13 @@ private static void parseError(String str, String msg) { } /** + * Parse a single type in a descriptor. Results can be: + *
    + *
  • A {@code Class} for successful parsing + *
  • {@code null} for malformed descriptor format + *
  • Throwing a {@link TypeNotPresentException} for valid class name, + * but class cannot be discovered + *
* @param loader the class loader in which to look up the types (null means * bootstrap class loader) */ @@ -100,7 +124,8 @@ private static Class parseSig(String str, int[] i, int end, ClassLoader loade t = t.arrayType(); return t; } else { - return Wrapper.forBasicType(c).primitiveType(); + var w = Wrapper.forPrimitiveTypeOrNull(c); + return w == null ? null : w.primitiveType(); } } diff --git a/src/java.base/share/classes/sun/invoke/util/Wrapper.java b/src/java.base/share/classes/sun/invoke/util/Wrapper.java index 4e8beaabb3486..361b35abfd80d 100644 --- a/src/java.base/share/classes/sun/invoke/util/Wrapper.java +++ b/src/java.base/share/classes/sun/invoke/util/Wrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -352,6 +352,19 @@ public static Wrapper forBasicType(char type) { throw basicTypeError(type); } + /** + * Return the primitive wrapper for the given char. Does not return + * {@code OBJECT}. Returns {@code null} to allow flexible error messages. + * Dedicated for {@link BytecodeDescriptor}. + */ + static Wrapper forPrimitiveTypeOrNull(char type) { + Wrapper w = FROM_CHAR[(type + (type >> 1)) & 0xf]; + if (w != null && w != OBJECT && w.basicTypeChar == type) { + return w; + } + return null; + } + @DontInline private static RuntimeException basicTypeError(char type) { for (Wrapper x : values()) { diff --git a/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java b/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java index 82751e3fcd293..74ed1e015531a 100644 --- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java +++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,12 +34,7 @@ import jdk.internal.reflect.ConstantPool; -import sun.reflect.generics.parser.SignatureParser; -import sun.reflect.generics.tree.TypeSignature; -import sun.reflect.generics.factory.GenericsFactory; -import sun.reflect.generics.factory.CoreReflectionFactory; -import sun.reflect.generics.visitor.Reifier; -import sun.reflect.generics.scope.ClassScope; +import sun.invoke.util.BytecodeDescriptor; /** * Parser for Java programming language annotations. Translates @@ -429,19 +424,11 @@ private static Object parseClassValue(ByteBuffer buf, } private static Class parseSig(String sig, Class container) { - if (sig.equals("V")) return void.class; - SignatureParser parser = SignatureParser.make(); - TypeSignature typeSig = parser.parseTypeSig(sig); - GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container)); - Reifier reify = Reifier.make(factory); - typeSig.accept(reify); - Type result = reify.getResult(); - return toClass(result); - } - static Class toClass(Type o) { - if (o instanceof GenericArrayType gat) - return toClass(gat.getGenericComponentType()).arrayType(); - return (Class) o; + try { + return BytecodeDescriptor.parseClass(sig, container.getClassLoader()); + } catch (IllegalArgumentException ex) { + throw new GenericSignatureFormatError(ex.getMessage()); + } } /**