Skip to content

Commit

Permalink
8333377: Migrate Generic Signature parsing to ClassFile API
Browse files Browse the repository at this point in the history
  • Loading branch information
liach committed Dec 5, 2024
1 parent bedb68a commit dea7a23
Show file tree
Hide file tree
Showing 65 changed files with 1,101 additions and 3,589 deletions.
76 changes: 22 additions & 54 deletions src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
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;
Expand Down Expand Up @@ -82,13 +80,10 @@
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.generics.info.ClassGenericInfo;
import sun.reflect.generics.info.GenericInfo;
import sun.reflect.annotation.*;

/**
Expand Down Expand Up @@ -1021,13 +1016,12 @@ Object getClassData() {
* <cite>The Java Virtual Machine Specification</cite>
* @since 1.5
*/
@SuppressWarnings("unchecked")
public TypeVariable<Class<T>>[] getTypeParameters() {
ClassRepository info = getGenericInfo();
var info = getGenericInfo();
if (info != null)
return (TypeVariable<Class<T>>[])info.getTypeParameters();
return info.getTypeVariables();
else
return (TypeVariable<Class<T>>[])new TypeVariable<?>[0];
return GenericInfo.emptyTypeVars();
}


Expand Down Expand Up @@ -1077,7 +1071,7 @@ public TypeVariable<Class<T>>[] getTypeParameters() {
* @since 1.5
*/
public Type getGenericSuperclass() {
ClassRepository info = getGenericInfo();
var info = getGenericInfo();
if (info == null) {
return getSuperclass();
}
Expand Down Expand Up @@ -1270,7 +1264,7 @@ private Class<?>[] getInterfaces(boolean cloneArray) {
* @since 1.5
*/
public Type[] getGenericInterfaces() {
ClassRepository info = getGenericInfo();
var info = getGenericInfo();
return (info == null) ? getInterfaces() : info.getSuperInterfaces();
}

Expand Down Expand Up @@ -1437,17 +1431,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<Class<?>> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader());
Class<?> returnType = types.removeLast();
Class<?>[] parameterClasses = types.toArray(GenericInfo.EMPTY_CLASS_ARRAY);

final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
Expand Down Expand Up @@ -1536,12 +1523,6 @@ boolean isPartial() {

}

private static Class<?> toClass(Type o) {
if (o instanceof GenericArrayType gat)
return toClass(gat.getGenericComponentType()).arrayType();
return (Class<?>)o;
}

/**
* If this {@code Class} object represents a local or anonymous
* class within a constructor, returns a {@link
Expand All @@ -1566,17 +1547,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<Class<?>> types = BytecodeDescriptor.parseMethod(enclosingInfo.getDescriptor(), getClassLoader());
types.removeLast();
Class<?>[] parameterClasses = types.toArray(GenericInfo.EMPTY_CLASS_ARRAY);

final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
Constructor<?>[] candidates = enclosingCandidate
Expand Down Expand Up @@ -2876,28 +2850,22 @@ private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> old
private native String getGenericSignature0();

// Generic info repository; lazily initialized
private transient volatile ClassRepository genericInfo;

// accessor for factory
private GenericsFactory getFactory() {
// create scope and factory
return CoreReflectionFactory.make(this, ClassScope.make(this));
}
private transient volatile @Stable ClassGenericInfo<T> genericInfo;

// accessor for generic info repository;
// generic info is lazily initialized
private ClassRepository getGenericInfo() {
ClassRepository genericInfo = this.genericInfo;
private ClassGenericInfo<T> getGenericInfo() {
var genericInfo = this.genericInfo;
if (genericInfo == null) {
String signature = getGenericSignature0();
if (signature == null) {
genericInfo = ClassRepository.NONE;
genericInfo = ClassGenericInfo.dummy();
} else {
genericInfo = ClassRepository.make(signature, getFactory());
genericInfo = new ClassGenericInfo<>(this, signature);
}
this.genericInfo = genericInfo;
}
return (genericInfo != ClassRepository.NONE) ? genericInfo : null;
return (genericInfo != ClassGenericInfo.dummy()) ? genericInfo : null;
}

// Annotations handling
Expand Down
49 changes: 12 additions & 37 deletions src/java.base/share/classes/java/lang/reflect/Constructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@
import jdk.internal.vm.annotation.Stable;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.repository.GenericDeclRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.scope.ConstructorScope;
import sun.reflect.generics.info.ExecutableGenericInfo;
import sun.reflect.generics.info.GenericInfo;

import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.util.StringJoiner;
Expand Down Expand Up @@ -76,22 +74,17 @@ public final class Constructor<T> extends Executable {
private final byte[] parameterAnnotations;

// Generics infrastructure
// Accessor for factory
private GenericsFactory getFactory() {
// create scope and factory
return CoreReflectionFactory.make(this, ConstructorScope.make(this));
}

// Accessor for generic info repository
@Override
ConstructorRepository getGenericInfo() {
ExecutableGenericInfo<Constructor<T>> getGenericInfo() {
assert hasGenericInformation();
var genericInfo = this.genericInfo;
if (genericInfo == null) {
var root = this.root;
if (root != null) {
genericInfo = root.getGenericInfo();
} else {
genericInfo = ConstructorRepository.make(getSignature(), getFactory());
genericInfo = new ExecutableGenericInfo<>(this, signature);
}
this.genericInfo = genericInfo;
}
Expand All @@ -104,7 +97,7 @@ ConstructorRepository getGenericInfo() {
* Some lazily initialized immutable states can be stored on root and shared to the copies.
*/
private Constructor<T> root;
private transient volatile ConstructorRepository genericInfo;
private transient volatile ExecutableGenericInfo<Constructor<T>> genericInfo;
private @Stable ConstructorAccessor constructorAccessor;
// End shared states

Expand Down Expand Up @@ -199,7 +192,7 @@ void checkCanSetAccessible(Class<?> caller) {

@Override
boolean hasGenericInformation() {
return (getSignature() != null);
return signature != null;
}

@Override
Expand Down Expand Up @@ -240,12 +233,11 @@ public int getModifiers() {
* @since 1.5
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public TypeVariable<Constructor<T>>[] getTypeParameters() {
if (getSignature() != null) {
return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters();
} else
return (TypeVariable<Constructor<T>>[])GenericDeclRepository.EMPTY_TYPE_VARS;
if (hasGenericInformation()) {
return getGenericInfo().getTypeVariables();
} else
return GenericInfo.emptyTypeVars();
}


Expand Down Expand Up @@ -569,23 +561,6 @@ void setConstructorAccessor(ConstructorAccessor accessor) {
}
}

int getSlot() {
return slot;
}

String getSignature() {
return signature;
}

byte[] getRawAnnotations() {
return annotations;
}

byte[] getRawParameterAnnotations() {
return parameterAnnotations;
}


/**
* {@inheritDoc}
*
Expand Down
8 changes: 4 additions & 4 deletions src/java.base/share/classes/java/lang/reflect/Executable.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.generics.info.ExecutableGenericInfo;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import sun.reflect.generics.repository.ConstructorRepository;

/**
* A shared superclass for the common functionality of {@link Method}
Expand All @@ -67,7 +67,7 @@ public abstract sealed class Executable extends AccessibleObject
*/
abstract boolean hasGenericInformation();

abstract ConstructorRepository getGenericInfo();
abstract ExecutableGenericInfo<?> getGenericInfo();

boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
/* Avoid unnecessary cloning */
Expand Down Expand Up @@ -331,7 +331,7 @@ public Set<AccessFlag> accessFlags() {
@SuppressWarnings("doclint:reference") // cross-module links
public Type[] getGenericParameterTypes() {
if (hasGenericInformation())
return getGenericInfo().getParameterTypes();
return getGenericInfo().getParameters();
else
return getParameterTypes();
}
Expand Down Expand Up @@ -533,7 +533,7 @@ byte[] getTypeAnnotationBytes() {
public Type[] getGenericExceptionTypes() {
Type[] result;
if (hasGenericInformation() &&
((result = getGenericInfo().getExceptionTypes()).length > 0))
((result = getGenericInfo().getExceptions()).length > 0))
return result;
else
return getExceptionTypes();
Expand Down
26 changes: 7 additions & 19 deletions src/java.base/share/classes/java/lang/reflect/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.generics.repository.FieldRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.scope.ClassScope;
import sun.reflect.generics.info.FieldGenericInfo;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -84,31 +81,22 @@ class Field extends AccessibleObject implements Member {
* Some lazily initialized immutable states can be stored on root and shared to the copies.
*/
private Field root;
private transient volatile FieldRepository genericInfo;
private transient volatile FieldGenericInfo genericInfo;
private @Stable FieldAccessor fieldAccessor; // access control enabled
private @Stable FieldAccessor overrideFieldAccessor; // access control suppressed
// End shared states

// Generics infrastructure

private String getGenericSignature() {return signature;}

// Accessor for factory
private GenericsFactory getFactory() {
Class<?> c = getDeclaringClass();
// create scope and factory
return CoreReflectionFactory.make(c, ClassScope.make(c));
}

// Accessor for generic info repository
private FieldRepository getGenericInfo() {
private FieldGenericInfo getGenericInfo() {
assert signature != null;
var genericInfo = this.genericInfo;
if (genericInfo == null) {
var root = this.root;
if (root != null) {
genericInfo = root.getGenericInfo();
} else {
genericInfo = FieldRepository.make(getGenericSignature(), getFactory());
genericInfo = new FieldGenericInfo(getDeclaringClass(), signature);
}
this.genericInfo = genericInfo;
}
Expand Down Expand Up @@ -286,8 +274,8 @@ public Class<?> getType() {
* @since 1.5
*/
public Type getGenericType() {
if (getGenericSignature() != null)
return getGenericInfo().getGenericType();
if (signature != null)
return getGenericInfo().getType();
else
return getType();
}
Expand Down
Loading

0 comments on commit dea7a23

Please sign in to comment.