Skip to content

Commit 8370854

Browse files
committed
8356022: Migrate descriptor parsing from generics to BytecodeDescriptor
1 parent de801fe commit 8370854

File tree

4 files changed

+58
-49
lines changed

4 files changed

+58
-49
lines changed

src/java.base/share/classes/java/lang/Class.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import java.lang.reflect.Member;
4848
import java.lang.reflect.Method;
4949
import java.lang.reflect.Modifier;
50-
import java.lang.reflect.Proxy;
5150
import java.lang.reflect.RecordComponent;
5251
import java.lang.reflect.Type;
5352
import java.lang.reflect.TypeVariable;
@@ -82,12 +81,11 @@
8281
import jdk.internal.vm.annotation.IntrinsicCandidate;
8382
import jdk.internal.vm.annotation.Stable;
8483

84+
import sun.invoke.util.BytecodeDescriptor;
8585
import sun.invoke.util.Wrapper;
8686
import sun.reflect.generics.factory.CoreReflectionFactory;
8787
import sun.reflect.generics.factory.GenericsFactory;
8888
import sun.reflect.generics.repository.ClassRepository;
89-
import sun.reflect.generics.repository.MethodRepository;
90-
import sun.reflect.generics.repository.ConstructorRepository;
9189
import sun.reflect.generics.scope.ClassScope;
9290
import sun.reflect.annotation.*;
9391

@@ -1435,17 +1433,10 @@ public Method getEnclosingMethod() {
14351433
if (!enclosingInfo.isMethod())
14361434
return null;
14371435

1438-
MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(),
1439-
getFactory());
1440-
Class<?> returnType = toClass(typeInfo.getReturnType());
1441-
Type [] parameterTypes = typeInfo.getParameterTypes();
1442-
Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
1443-
1444-
// Convert Types to Classes; returned types *should*
1445-
// be class objects since the methodDescriptor's used
1446-
// don't have generics information
1447-
for(int i = 0; i < parameterClasses.length; i++)
1448-
parameterClasses[i] = toClass(parameterTypes[i]);
1436+
// Descriptor already validated by VM
1437+
List<Class<?>> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader());
1438+
Class<?> returnType = types.removeLast();
1439+
Class<?>[] parameterClasses = types.toArray(EMPTY_CLASS_ARRAY);
14491440

14501441
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
14511442
Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
@@ -1564,17 +1555,10 @@ public Constructor<?> getEnclosingConstructor() {
15641555
if (!enclosingInfo.isConstructor())
15651556
return null;
15661557

1567-
ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(),
1568-
getFactory());
1569-
Type [] parameterTypes = typeInfo.getParameterTypes();
1570-
Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
1571-
1572-
// Convert Types to Classes; returned types *should*
1573-
// be class objects since the methodDescriptor's used
1574-
// don't have generics information
1575-
for (int i = 0; i < parameterClasses.length; i++)
1576-
parameterClasses[i] = toClass(parameterTypes[i]);
1577-
1558+
// Descriptor already validated by VM
1559+
List<Class<?>> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader());
1560+
types.removeLast();
1561+
Class<?>[] parameterClasses = types.toArray(EMPTY_CLASS_ARRAY);
15781562

15791563
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
15801564
Constructor<?>[] candidates = enclosingCandidate
@@ -1880,7 +1864,7 @@ public Class<?>[] getClasses() {
18801864
}
18811865
currentClass = currentClass.getSuperclass();
18821866
}
1883-
return list.toArray(new Class<?>[0]);
1867+
return list.toArray(EMPTY_CLASS_ARRAY);
18841868
}
18851869

18861870

src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -37,9 +37,26 @@ public class BytecodeDescriptor {
3737

3838
private BytecodeDescriptor() { } // cannot instantiate
3939

40+
/**
41+
* @throws IllegalArgumentException if the descriptor is invalid
42+
* @throws TypeNotPresentException if the descriptor is valid, but
43+
* the class cannot be found by the loader
44+
*/
45+
public static Class<?> parseClass(String descriptor, ClassLoader loader) {
46+
int[] i = {0};
47+
var ret = parseSig(descriptor, i, descriptor.length(), loader);
48+
if (i[0] != descriptor.length() || ret == null) {
49+
parseError("not a class descriptor", descriptor);
50+
}
51+
return ret;
52+
}
53+
4054
/**
4155
* @param loader the class loader in which to look up the types (null means
4256
* bootstrap class loader)
57+
* @throws IllegalArgumentException if the descriptor is invalid
58+
* @throws TypeNotPresentException if the descriptor is valid, but
59+
* a reference type cannot be found by the loader
4360
*/
4461
public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
4562
return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
@@ -78,6 +95,13 @@ private static void parseError(String str, String msg) {
7895
}
7996

8097
/**
98+
* Parse a single type in a descriptor. Results can be:
99+
* <ul>
100+
* <li>A {@code Class} for successful parsing
101+
* <li>{@code null} for malformed descriptor format
102+
* <li>Throwing a {@link TypeNotPresentException} for valid class name,
103+
* but class cannot be discovered
104+
* </ul>
81105
* @param loader the class loader in which to look up the types (null means
82106
* bootstrap class loader)
83107
*/
@@ -100,7 +124,8 @@ private static Class<?> parseSig(String str, int[] i, int end, ClassLoader loade
100124
t = t.arrayType();
101125
return t;
102126
} else {
103-
return Wrapper.forBasicType(c).primitiveType();
127+
var w = Wrapper.forPrimitiveTypeOrNull(c);
128+
return w == null ? null : w.primitiveType();
104129
}
105130
}
106131

src/java.base/share/classes/sun/invoke/util/Wrapper.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -352,6 +352,19 @@ public static Wrapper forBasicType(char type) {
352352
throw basicTypeError(type);
353353
}
354354

355+
/**
356+
* Return the primitive wrapper for the given char. Does not return
357+
* {@code OBJECT}. Returns {@code null} to allow flexible error messages.
358+
* Dedicated for {@link BytecodeDescriptor}.
359+
*/
360+
static Wrapper forPrimitiveTypeOrNull(char type) {
361+
Wrapper w = FROM_CHAR[(type + (type >> 1)) & 0xf];
362+
if (w != null && w != OBJECT && w.basicTypeChar == type) {
363+
return w;
364+
}
365+
return null;
366+
}
367+
355368
@DontInline
356369
private static RuntimeException basicTypeError(char type) {
357370
for (Wrapper x : values()) {

src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -34,12 +34,7 @@
3434

3535
import jdk.internal.reflect.ConstantPool;
3636

37-
import sun.reflect.generics.parser.SignatureParser;
38-
import sun.reflect.generics.tree.TypeSignature;
39-
import sun.reflect.generics.factory.GenericsFactory;
40-
import sun.reflect.generics.factory.CoreReflectionFactory;
41-
import sun.reflect.generics.visitor.Reifier;
42-
import sun.reflect.generics.scope.ClassScope;
37+
import sun.invoke.util.BytecodeDescriptor;
4338

4439
/**
4540
* Parser for Java programming language annotations. Translates
@@ -429,19 +424,11 @@ private static Object parseClassValue(ByteBuffer buf,
429424
}
430425

431426
private static Class<?> parseSig(String sig, Class<?> container) {
432-
if (sig.equals("V")) return void.class;
433-
SignatureParser parser = SignatureParser.make();
434-
TypeSignature typeSig = parser.parseTypeSig(sig);
435-
GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container));
436-
Reifier reify = Reifier.make(factory);
437-
typeSig.accept(reify);
438-
Type result = reify.getResult();
439-
return toClass(result);
440-
}
441-
static Class<?> toClass(Type o) {
442-
if (o instanceof GenericArrayType gat)
443-
return toClass(gat.getGenericComponentType()).arrayType();
444-
return (Class<?>) o;
427+
try {
428+
return BytecodeDescriptor.parseClass(sig, container.getClassLoader());
429+
} catch (IllegalArgumentException ex) {
430+
throw new GenericSignatureFormatError(ex.getMessage());
431+
}
445432
}
446433

447434
/**

0 commit comments

Comments
 (0)