Skip to content

Commit

Permalink
Address review 1/n
Browse files Browse the repository at this point in the history
  • Loading branch information
biboudis committed Jun 19, 2024
1 parent 875eb34 commit 0eab5db
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 93 deletions.
90 changes: 30 additions & 60 deletions src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
package java.lang;

import java.lang.annotation.Annotation;
import java.lang.classfile.Attribute;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
Expand Down Expand Up @@ -105,7 +105,7 @@
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.repository.ExecutableRepository;
import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants;
import sun.reflect.annotation.*;
Expand Down Expand Up @@ -1737,7 +1737,7 @@ public Constructor<?> getEnclosingConstructor() throws SecurityException {
if (!enclosingInfo.isConstructor())
return null;

ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(),
ExecutableRepository typeInfo = ExecutableRepository.make(enclosingInfo.getDescriptor(),
getFactory());
Type [] parameterTypes = typeInfo.getParameterTypes();
Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
Expand Down Expand Up @@ -2305,8 +2305,8 @@ public Constructor<?>[] getConstructors() throws SecurityException {
}

private Method[] filterOutDeconstructorsFromMethods(Method[] in) {
if (this.getClassLoader() != null ) {
Map<String, Boolean> isNotPattern = new HashMap<>();
if (this.getClassLoader() != null) {
Set<String> isPattern = new HashSet<>();
ClassModel cm = null;
try (InputStream resource = this.getClassLoader().getResourceAsStream(getName() + ".class")) {
if (resource == null) {
Expand All @@ -2318,13 +2318,10 @@ private Method[] filterOutDeconstructorsFromMethods(Method[] in) {
throw new RuntimeException(e);
}
for (MethodModel mm : cm.methods()) {
PatternAttribute pa = null;
for (Attribute<?> attribute : mm.attributes()) {
if (attribute instanceof PatternAttribute pap) pa = pap;
}
isNotPattern.put(mm.methodName().stringValue(), pa == null);
PatternAttribute pa = mm.findAttribute(Attributes.pattern()).orElse(null);
if (pa != null) isPattern.add(mm.methodName().stringValue());
}
Method[] ret = Arrays.stream(in).filter(m -> isNotPattern.getOrDefault(m.getName(), true)).toArray(Method[]::new);
Method[] ret = Arrays.stream(in).filter(m -> !isPattern.contains(m.getName())).toArray(Method[]::new);
return ret;
} else {
return in;
Expand Down Expand Up @@ -2353,12 +2350,12 @@ private Method[] filterOutDeconstructorsFromMethods(Method[] in) {

/**
* Returns a {@code Deconstructor} object that reflects the specified
* public constructor of the class represented by this {@code Class}
* public deconstructor of the class represented by this {@code Class}
* object.
*
* @param bindingTypes the array of the types of the bindings.
* @return the {@code Constructor} object of the public constructor that
* matches the specified {@code parameterTypes}
* @return the {@code Deconstructor} object of the public deconstructor that
* matches the specified {@code bindingTypes}
* @throws NoSuchPatternException if a matching deconstructor is not found.
*
* @throws SecurityException
Expand Down Expand Up @@ -2423,19 +2420,13 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi
byte[] bytes = is.readAllBytes();
ClassModel cm = ClassFile.of().parse(bytes);
for (MethodModel mm : cm.methods()) {
PatternAttribute pa = null;
for (Attribute<?> attribute : mm.attributes()) {
if (attribute instanceof PatternAttribute pa_) pa = pa_;
}
PatternAttribute pa = mm.findAttribute(Attributes.pattern()).orElse(null);
if (pa != null) {
String descriptorFilter = null;

// generic signature detection
SignatureAttribute sa = null;
for (Attribute<?> attribute : pa.attributes()) {
if (attribute instanceof SignatureAttribute sa_) sa = sa_;
}
List<String> signatures = List.of();
SignatureAttribute sa = pa.findAttribute(Attributes.signature()).orElse(null);
List<String> signatures = null;
if (sa != null) {
signatures = sa.asMethodSignature().arguments().stream().map(a -> a.signatureString()).toList();
} else {
Expand All @@ -2451,17 +2442,8 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi
if ((params.length == 0 || (params.length != 0 && pa.patternTypeSymbol().descriptorString().equals(descriptorFilter))) &&
(which == Member.DECLARED || mm.flags().has(AccessFlag.PUBLIC))) {
// binding annotations
RuntimeVisibleAnnotationsAttribute rva = null;
for (Attribute<?> attribute : mm.attributes()) {
if (attribute instanceof RuntimeVisibleAnnotationsAttribute rva_) rva = rva_;
}
ByteBuffer assembled_rva = null;
if (rva != null) {
byte rvaBytes[] = ((BoundAttribute) rva).contents(); // returns the full attribute
int rva_length = ((BoundAttribute) rva).payloadLen(); // already comes after the subtraction with 4
assembled_rva = ByteBuffer.wrap(rvaBytes, 0, rva_length);
// TODO: RuntimeInVisibleAnnotationsAttribute
}
RuntimeVisibleAnnotationsAttribute rva = mm.findAttribute(Attributes.runtimeVisibleAnnotations()).orElse(null);
ByteBuffer assembled_rva = getAnnotationContents(rva != null, (BoundAttribute) rva);

ArrayList<PatternBinding> deconstructorBindings = new ArrayList<>();
Deconstructor<?> currentDeconstructor = new Deconstructor<T>(this,
Expand All @@ -2475,37 +2457,16 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi

// parameter names
var parameterList = pa.patternTypeSymbol().parameterList();
MethodParametersAttribute mp = null;
for (Attribute<?> attribute : pa.attributes()) {
if (attribute instanceof MethodParametersAttribute mp_) mp = mp_;
}
MethodParametersAttribute mp = pa.findAttribute(Attributes.methodParameters()).orElse(null);
List<String> parameterNameList = mp.parameters().stream().map(p -> p.name().get().stringValue()).toList();

// binding annotations
RuntimeVisibleParameterAnnotationsAttribute rvpa = null;
for (Attribute<?> attribute : pa.attributes()) {
if (attribute instanceof RuntimeVisibleParameterAnnotationsAttribute rvpa_) rvpa = rvpa_;
}
ByteBuffer assembled_rvpa = null;
if (rvpa != null) {
byte rvpaBytes[] = ((BoundAttribute) rvpa).contents();
int rvpa_length = ((BoundAttribute) rvpa).payloadLen();
assembled_rvpa = ByteBuffer.wrap(rvpaBytes, 0, rvpa_length);
// TODO: RuntimeInVisibleParameterAnnotationsAttribute
}
RuntimeVisibleParameterAnnotationsAttribute rvpa = pa.findAttribute(Attributes.runtimeVisibleParameterAnnotations()).orElse(null);
ByteBuffer assembled_rvpa = getAnnotationContents(rvpa != null, (BoundAttribute) rvpa);

// binding type annotations
RuntimeVisibleTypeAnnotationsAttribute rvta = null;
for (Attribute<?> attribute : pa.attributes()) {
if (attribute instanceof RuntimeVisibleTypeAnnotationsAttribute rvta_) rvta = rvta_;
}
ByteBuffer assembled_rvta = null;
if (rvpa != null) {
byte rvtaBytes[] = ((BoundAttribute) rvpa).contents();
int rvta_length = ((BoundAttribute) rvpa).payloadLen();
assembled_rvta = ByteBuffer.wrap(rvtaBytes, 0, rvta_length);
// TODO: RuntimeInVisibleTypeAnnotationsAttribute
}
RuntimeVisibleTypeAnnotationsAttribute rvta = pa.findAttribute(Attributes.runtimeVisibleTypeAnnotations()).orElse(null);
ByteBuffer assembled_rvta = getAnnotationContents(rvta != null, (BoundAttribute) rvta);

for (int i = 0; i < parameterList.size(); i++) {
Class<?> bindingClass = parameterList.get(i).resolveConstantDesc(MethodHandles.lookup());
Expand All @@ -2531,6 +2492,15 @@ private Deconstructor<?>[] getDeclaredDeconstructors0(Class<?>[] params, int whi
return decs.toArray(new Deconstructor<?>[decs.size()]);
}

private static ByteBuffer getAnnotationContents(boolean exists, BoundAttribute<?> boundAttribute) {
if (exists) {
byte rvpaBytes[] = boundAttribute.contents();
int rvpa_length = boundAttribute.payloadLen();
return ByteBuffer.wrap(rvpaBytes, 0, rvpa_length);
}
return null;
}

/**
* Returns a {@code Deconstructor} object that reflects the specified
* deconstructor of the class represented by this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 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
Expand Down Expand Up @@ -28,7 +28,7 @@
/**
* Thrown when a particular pattern cannot be found.
*
* @since 1.0
* @since 24
*/
public class NoSuchPatternException extends ReflectiveOperationException {
@java.io.Serial
Expand Down
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/lang/reflect/AccessFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public Set<Location> apply(ClassFileFormatVersion cffv) {
new Function<ClassFileFormatVersion, Set<Location>>() {
@Override
public Set<Location> apply(ClassFileFormatVersion cffv) {
return (cffv.compareTo(ClassFileFormatVersion.RELEASE_22) >= 0 ) ?
return (cffv.compareTo(ClassFileFormatVersion.RELEASE_24) >= 0 ) ?
Location.SET_PATTERN :
Location.EMPTY_SET;}
}),
Expand All @@ -394,7 +394,7 @@ public Set<Location> apply(ClassFileFormatVersion cffv) {
new Function<ClassFileFormatVersion, Set<Location>>() {
@Override
public Set<Location> apply(ClassFileFormatVersion cffv) {
return (cffv.compareTo(ClassFileFormatVersion.RELEASE_22) >= 0 ) ?
return (cffv.compareTo(ClassFileFormatVersion.RELEASE_24) >= 0 ) ?
Location.SET_PATTERN :
Location.EMPTY_SET;}
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
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.ExecutableRepository;
import sun.reflect.generics.repository.GenericDeclRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
Expand Down Expand Up @@ -73,7 +73,7 @@ public final class Constructor<T> extends Executable {
// Generics and annotations support
private final transient String signature;
// generic info repository; lazily initialized
private transient volatile ConstructorRepository genericInfo;
private transient volatile ExecutableRepository genericInfo;
private final byte[] annotations;
private final byte[] parameterAnnotations;

Expand All @@ -86,13 +86,13 @@ private GenericsFactory getFactory() {

// Accessor for generic info repository
@Override
ConstructorRepository getGenericInfo() {
ExecutableRepository getGenericInfo() {
var genericInfo = this.genericInfo;
// lazily initialize repository if necessary
if (genericInfo == null) {
// create and cache generic info repository
genericInfo =
ConstructorRepository.make(getSignature(),
ExecutableRepository.make(getSignature(),
getFactory());
this.genericInfo = genericInfo;
}
Expand Down
31 changes: 23 additions & 8 deletions src/java.base/share/classes/java/lang/reflect/Deconstructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@

import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.repository.ExecutableRepository;
import sun.reflect.generics.repository.GenericDeclRepository;
import sun.reflect.generics.scope.DeconstructorScope;
import sun.reflect.generics.tree.MethodTypeSignature;

import java.lang.annotation.Annotation;
import java.lang.invoke.MethodType;
Expand Down Expand Up @@ -60,14 +60,15 @@
public final class Deconstructor<T> extends Executable {
private final Class<T> clazz;
private final int slot;
private ArrayList<PatternBinding> patternBindings;

private final int modifiers;
private final int patternFlags;
// Generics and annotations support
private final transient String signature;
// generic info repository; lazily initialized
private transient volatile ConstructorRepository genericInfo;
private transient volatile ExecutableRepository genericInfo;
private final byte[] annotations;
private ArrayList<PatternBinding> patternBindings;

// Generics infrastructure
// Accessor for factory
Expand Down Expand Up @@ -121,7 +122,7 @@ public Deconstructor(Class<T> declaringClass,
*/
Deconstructor<T> copy() {
// This routine enables sharing of ConstructorAccessor objects
// among Constructor objects which refer to the same underlying
// among Deconstructor objects which refer to the same underlying
// method in the VM. (All of this contortion is only necessary
// because of the "accessibility" bit in AccessibleObject,
// which implicitly requires that new java.lang.reflect
Expand All @@ -145,7 +146,7 @@ Deconstructor<T> copy() {
* {@inheritDoc}
*
* <p> A {@code SecurityException} is also thrown if this object is a
* {@code Constructor} object for the class {@code Class} and {@code flag}
* {@code Deconstructor} object for the class {@code Class} and {@code flag}
* is true. </p>
*
* @param flag {@inheritDoc}
Expand Down Expand Up @@ -216,6 +217,20 @@ public Annotation[][] getParameterAnnotations() {
return new Annotation[0][];
}

/**
* Returns an array of arrays of {@code Annotation}s that
* represent the annotations on the bindings, in
* declaration order, of the {@code Deconstructor} represented by
* this object.
*
* @return an array of arrays that represent the annotations on
* the bindings, in declaration order, of
* the deconstructor represented by this object
*/
public Annotation[][] getBindingAnnotations() {
return patternBindings.stream().map(pb -> pb.getAnnotations()).toArray(Annotation[][]::new);
}

@Override
boolean handleParameterNumberMismatch(int resultLength, Class<?>[] parameterTypes) {
return false;
Expand Down Expand Up @@ -315,13 +330,13 @@ boolean hasGenericInformation() {
return false;
}

ConstructorRepository getGenericInfo() {
ExecutableRepository getGenericInfo() {
var genericInfo = this.genericInfo;
// lazily initialize repository if necessary
if (genericInfo == null) {
// create and cache generic info repository
genericInfo =
ConstructorRepository.make(getSignature(),
ExecutableRepository.make(getSignature(),
getFactory());
this.genericInfo = genericInfo;
}
Expand Down
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/lang/reflect/Executable.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.repository.ExecutableRepository;

/**
* 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 ExecutableRepository getGenericInfo();

boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
/* Avoid unnecessary cloning */
Expand Down
Loading

0 comments on commit 0eab5db

Please sign in to comment.