diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 900369d7188..fb7a2f70102 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -47,26 +47,27 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectStreamField; +import java.lang.reflect.AccessFlag; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.AccessFlag; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Deconstructor; -import java.lang.reflect.PatternBinding; 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.constant.Constable; +import java.lang.reflect.MemberPattern; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.PatternBinding; import java.lang.reflect.Proxy; import java.lang.reflect.RecordComponent; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; -import java.lang.constant.Constable; import java.net.URL; import java.nio.ByteBuffer; import java.security.AccessController; @@ -88,7 +89,6 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.constant.ConstantUtils; -import jdk.internal.javac.PreviewFeature; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.misc.Unsafe; @@ -113,7 +113,6 @@ import sun.reflect.annotation.*; import sun.reflect.misc.ReflectUtil; -import static java.lang.ClassLoader.getPlatformClassLoader; import static java.lang.constant.ConstantDescs.CD_void; /** @@ -2343,7 +2342,7 @@ private Method[] filterOutDeconstructorsFromMethods(Method[] in) { * @see #getDeclaredDeconstructors() * @since 23 */ - public Deconstructor [] getDeconstructors() throws SecurityException { + public Deconstructor[] getDeconstructors() throws SecurityException { return getDeclaredDeconstructors0(EMPTY_CLASS_ARRAY, Member.PUBLIC); } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index ab972d4d120..74761e63519 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -43,13 +43,7 @@ import java.lang.constant.ConstantDescs; import java.lang.invoke.LambdaForm.BasicType; import java.lang.invoke.MethodHandleImpl.Intrinsic; -import java.lang.reflect.Constructor; -import java.lang.reflect.Deconstructor; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.PatternBinding; +import java.lang.reflect.*; import java.nio.ByteOrder; import java.security.ProtectionDomain; import java.util.ArrayList; @@ -71,8 +65,6 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; import static java.lang.invoke.MethodType.methodType; -import java.lang.runtime.Carriers; - /** * This class consists exclusively of static methods that operate on or return * method handles. They fall into several categories: diff --git a/src/java.base/share/classes/java/lang/reflect/Deconstructor.java b/src/java.base/share/classes/java/lang/reflect/Deconstructor.java index c9bc22eb1e9..4b2b433f89f 100644 --- a/src/java.base/share/classes/java/lang/reflect/Deconstructor.java +++ b/src/java.base/share/classes/java/lang/reflect/Deconstructor.java @@ -1,53 +1,12 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - package java.lang.reflect; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; -import sun.reflect.generics.factory.CoreReflectionFactory; -import sun.reflect.generics.factory.GenericsFactory; -import sun.reflect.generics.repository.ExecutableRepository; -import sun.reflect.generics.repository.GenericDeclRepository; -import sun.reflect.generics.scope.DeconstructorScope; - -import java.lang.annotation.Annotation; -import java.lang.invoke.MethodType; -import java.lang.runtime.Carriers; import java.util.ArrayList; -import java.util.Arrays; -import java.util.StringJoiner; -import java.util.stream.Collectors; - -import static java.lang.runtime.PatternBytecodeName.mangle; /** * {@code Deconstructor} provides information about, and access to, a single * deconstructor for a class. * - * @param the class in which the constructor is declared + * @param the class in which the deconstructor is declared * * @see Member * @see Class @@ -58,47 +17,20 @@ * * @since 24 */ -public final class Deconstructor extends Executable { - private final Class clazz; - private final int slot; - private ArrayList 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 ExecutableRepository genericInfo; - private final byte[] annotations; - - // Generics infrastructure - // Accessor for factory - private GenericsFactory getFactory() { - // create scope and factory - return CoreReflectionFactory.make(this, DeconstructorScope.make(this)); - } - - private Deconstructor root; - - @Override - Deconstructor getRoot() { - return root; - } - +public final class Deconstructor extends MemberPattern { /** * TODO make private again - * Package-private deconstructor used by ReflectAccess to enable + * Package-private member pattern used by ReflectAccess to enable * instantiation of these objects in Java code from the java.lang * package via jdk.internal.access.JavaLangReflectAccess. * * @param declaringClass x - * @param modifiers x + * @param modifiers x * @param patternFlags x - * @param slot x - * @param patternBindings x - * @param signature x - * @param annotations x - * + * @param slot x + * @param patternBindings x + * @param signature x + * @param annotations x */ public Deconstructor(Class declaringClass, int modifiers, @@ -107,148 +39,16 @@ public Deconstructor(Class declaringClass, ArrayList patternBindings, String signature, byte[] annotations) { - this.clazz = declaringClass; - this.modifiers = modifiers; - this.patternFlags = patternFlags; - this.slot = slot; - this.patternBindings = patternBindings; - this.signature = signature; - this.annotations = annotations; - } - - /** - * Package-private routine (exposed to java.lang.Class via - * ReflectAccess) which returns a copy of this Constructor. The copy's - * "root" field points to this Deconstructor. - */ - Deconstructor copy() { - // This routine enables sharing of ConstructorAccessor objects - // 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 - // objects be fabricated for each reflective call on Class - // objects.) - if (this.root != null) - throw new IllegalArgumentException("Can not copy a non-root Constructor"); - - Deconstructor res = new Deconstructor<>(clazz, - modifiers, - patternFlags, - slot, - patternBindings, - signature, - annotations); - res.root = this; - return res; - } - - /** - * {@inheritDoc} - * - *

A {@code SecurityException} is also thrown if this object is a - * {@code Deconstructor} object for the class {@code Class} and {@code flag} - * is true.

- * - * @param flag {@inheritDoc} - * - * @throws InaccessibleObjectException {@inheritDoc} - * @throws SecurityException if the request is denied by the security manager - * or this is a constructor for {@code java.lang.Class} - * - */ - @Override - @CallerSensitive - public void setAccessible(boolean flag) { - AccessibleObject.checkPermission(); - if (flag) { - checkCanSetAccessible(Reflection.getCallerClass()); - } - setAccessible0(flag); - } - - @Override - void checkCanSetAccessible(Class caller) { - checkCanSetAccessible(caller, clazz); - if (clazz == Class.class) { - // can we change this to InaccessibleObjectException? - throw new SecurityException("Cannot make a java.lang.Class" - + " constructor accessible"); - } - } - - /** - * Returns the {@code Class} object representing the class that - * declares the constructor represented by this object. - */ - @Override - public Class getDeclaringClass() { - return clazz; - } - - /** - * Returns the name of this constructor, as a string. This is - * the binary name of the constructor's declaring class. - */ - @Override - public String getName() { - return getDeclaringClass().getName(); - } - - /** - * {@inheritDoc} - * @jls 8.8.3 Constructor Modifiers - */ - @Override - public int getModifiers() { - return modifiers; - } - - /** - * {@inheritDoc} - * @jls X.X.X Deconstructor Modifiers - */ - @Override - public boolean isSynthetic() { - return Modifier.isSynthetic(getModifiers()); - } - - @Override - 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; - } - - /** - * {@inheritDoc} - * @throws GenericSignatureFormatError {@inheritDoc} - * @since 1.5 - */ - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - public TypeVariable>[] getTypeParameters() { - if (getSignature() != null) { - return (TypeVariable>[])getGenericInfo().getTypeParameters(); - } else - return (TypeVariable>[])GenericDeclRepository.EMPTY_TYPE_VARS; + super(declaringClass, + null, + null, + modifiers, + patternFlags, + slot, + patternBindings, + signature, + annotations, + null); } @Override @@ -277,202 +77,22 @@ public Class[] getExceptionTypes() { } /** - * Returns a string describing this {@code Deconstructor}, - * including type parameters. The string is formatted as the - * constructor access modifiers, if any, followed by an - * angle-bracketed comma separated list of the constructor's type - * parameters, if any, including informative bounds of the - * type parameters, if any, followed by the fully-qualified name of the - * declaring class, followed by a parenthesized, comma-separated - * list of the constructor's generic formal parameter types. - * - * If this constructor was declared to take a variable number of - * arguments, instead of denoting the last parameter as - * "Type[]", it is denoted as - * "Type...". - * - * A space is used to separate access modifiers from one another - * and from the type parameters or class name. If there are no - * type parameters, the type parameter list is elided; if the type - * parameter list is present, a space separates the list from the - * class name. If the constructor is declared to throw - * exceptions, the parameter list is followed by a space, followed - * by the word "{@code throws}" followed by a - * comma-separated list of the generic thrown exception types. - * - *

The only possible modifiers for constructors are the access - * modifiers {@code public}, {@code protected} or - * {@code private}. Only one of these may appear, or none if the - * constructor has default (package) access. - * - * @return a string describing this {@code Constructor}, - * include type parameters - * - * @since 1.5 - * @jls 8.8.3 Constructor Modifiers - * @jls 8.9.2 Enum Body Declarations - */ - @Override - public String toGenericString() { - return sharedToGenericString(Modifier.constructorModifiers(), false); - } - - String getSignature() { - return signature; - } - - @Override - byte[] getAnnotationBytes() { - return annotations; - } - - @Override - boolean hasGenericInformation() { - return false; - } - - ExecutableRepository getGenericInfo() { - var genericInfo = this.genericInfo; - // lazily initialize repository if necessary - if (genericInfo == null) { - // create and cache generic info repository - genericInfo = - ExecutableRepository.make(getSignature(), - getFactory()); - this.genericInfo = genericInfo; - } - return genericInfo; //return cached repository - } - - @Override - void specificToStringHeader(StringBuilder sb) { - sb.append(getDeclaringClass().getTypeName()); - } - - @Override - void specificToGenericStringHeader(StringBuilder sb) { - specificToStringHeader(sb); - } - - - String sharedToGenericString(int modifierMask, boolean isDefault) { - try { - StringBuilder sb = new StringBuilder(); - - printModifiersIfNonzero(sb, modifierMask, isDefault); - - sb.append("pattern "); - TypeVariable[] typeparms = getTypeParameters(); - if (typeparms.length > 0) { - sb.append(Arrays.stream(typeparms) - .map(Executable::typeVarBounds) - .collect(Collectors.joining(",", "<", "> "))); - } - - specificToGenericStringHeader(sb); - - sb.append('('); - StringJoiner sj = new StringJoiner(","); - Type[] params = Arrays.stream(getPatternBindings()).map(pb -> pb.getGenericType()).toArray(Type[]::new); - for (int j = 0; j < params.length; j++) { - String param = params[j].getTypeName(); - if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... - param = param.replaceFirst("\\[\\]$", "..."); - sj.add(param); - } - sb.append(sj.toString()); - sb.append(')'); - - return sb.toString(); - } catch (Exception e) { - return "<" + e + ">"; - } - } - - /** - * Returns the pattern bindings of this deconstructor. - * - * @return pattern bindings - */ - public PatternBinding[] getPatternBindings() { - return patternBindings.toArray(PatternBinding[]::new); - } - - /** - * Returns the pattern flags of this deconstructor. - * - * @return pattern bindings - */ - public int getPatternFlags() { - return patternFlags; - } - - /** - * Initiate pattern matching of this deconstructor on the designated matchCandidate. - * - * @param matchCandidate the match candidate to perform pattern matching over. - * - * @return an array object created as a result of pattern matching - * - * @throws IllegalAccessException if this {@code Constructor} object - * is enforcing Java language access control and the underlying - * constructor is inaccessible. - * @throws MatchException if the pattern matching provoked - * by this deconstructor fails. - */ - public Object[] invoke(Object matchCandidate) - throws IllegalAccessException, MatchException - { - String underlyingName = getMangledName(); - - try { - Method method = getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass()); - method.setAccessible(override); - return (Object[])Carriers.boxedComponentValueArray( - MethodType.methodType( - Object.class, - Arrays.stream(this.getPatternBindings()) - .map(PatternBinding::getType) - .toArray(Class[]::new) - ) - ).invoke( - method.invoke(matchCandidate, matchCandidate) - ); - } catch (Throwable e) { - throw new MatchException(e.getMessage(), e); - } - } - - byte[] getRawAnnotations() { - return annotations; - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - @Override - public T getAnnotation(Class annotationClass) { - return super.getAnnotation(annotationClass); - } - - /** - * {@inheritDoc} - * @since 1.5 + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Deconstructor. The copy's + * "root" field points to this Deconstructor. */ - @Override - public Annotation[] getDeclaredAnnotations() { - return super.getDeclaredAnnotations(); - } - - @Override - public AnnotatedType getAnnotatedReturnType() { - return null; - } - - String getMangledName() { - return mangle(this.getDeclaringClass(), Arrays.stream(getPatternBindings()).map(pb -> pb.getType()).toArray(Class[]::new)); + Deconstructor copy() { + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root MemberPattern"); + + Deconstructor res = new Deconstructor<>(this.clazz, + this.modifiers, + this.patternFlags, + this.slot, + this.patternBindings, + this.signature, + this.annotations); + res.root = this; + return res; } } diff --git a/src/java.base/share/classes/java/lang/reflect/Executable.java b/src/java.base/share/classes/java/lang/reflect/Executable.java index b5a43c78d78..66dc6787a8e 100644 --- a/src/java.base/share/classes/java/lang/reflect/Executable.java +++ b/src/java.base/share/classes/java/lang/reflect/Executable.java @@ -50,7 +50,7 @@ * @since 1.8 */ public abstract sealed class Executable extends AccessibleObject - implements Member, GenericDeclaration permits Constructor, Deconstructor, Method { + implements Member, GenericDeclaration permits Constructor, MemberPattern, Method { /* * Only grant package-visibility to the constructor. */ diff --git a/src/java.base/share/classes/java/lang/reflect/MemberPattern.java b/src/java.base/share/classes/java/lang/reflect/MemberPattern.java new file mode 100644 index 00000000000..7293780731a --- /dev/null +++ b/src/java.base/share/classes/java/lang/reflect/MemberPattern.java @@ -0,0 +1,487 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.repository.ExecutableRepository; +import sun.reflect.generics.repository.GenericDeclRepository; +import sun.reflect.generics.scope.MemberPatternScope; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodType; +import java.lang.runtime.Carriers; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import static java.lang.runtime.PatternBytecodeName.mangle; + +/** + * {@code MemberPattern} provides information about, and access to, a single + * member pattern for a class. + * + * @param the class in which the member pattern is declared + * + * @see Executable + * @see Class + * + * @since 24 + */ +public abstract sealed class MemberPattern extends Executable permits Deconstructor { + final Class clazz; + final int slot; + final Class[] parameterTypes; + final Class[] exceptionTypes; + final ArrayList patternBindings; + + final int modifiers; + final int patternFlags; + // Generics and annotations support + final transient String signature; + // generic info repository; lazily initialized + transient volatile ExecutableRepository genericInfo; + final byte[] annotations; + + private final byte[] parameterAnnotations; + + // Generics infrastructure + // Accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, MemberPatternScope.make(this)); + } + + MemberPattern root; + + @Override + MemberPattern getRoot() { + return root; + } + + /** + * TODO make private again + * Package-private member pattern used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via jdk.internal.access.JavaLangReflectAccess. + * + * @param declaringClass x + * @param parameterTypes x + * @param checkedExceptions x + * @param modifiers x + * @param patternFlags x + * @param slot x + * @param patternBindings x + * @param signature x + * @param annotations x + * @param parameterAnnotations x + * + */ + public MemberPattern(Class declaringClass, + Class[] parameterTypes, + Class[] checkedExceptions, + int modifiers, + int patternFlags, + int slot, + ArrayList patternBindings, + String signature, + byte[] annotations, + byte[] parameterAnnotations) { + this.clazz = declaringClass; + this.parameterTypes = parameterTypes; + this.exceptionTypes = checkedExceptions; + this.modifiers = modifiers; + this.patternFlags = patternFlags; + this.slot = slot; + this.patternBindings = patternBindings; + this.signature = signature; + this.annotations = annotations; + this.parameterAnnotations = parameterAnnotations; + } + + /** + * {@inheritDoc} + * + *

A {@code SecurityException} is also thrown if this object is a + * {@code MemberPattern} object for the class {@code Class} and {@code flag} + * is true.

+ * + * @param flag {@inheritDoc} + * + * @throws InaccessibleObjectException {@inheritDoc} + * @throws SecurityException if the request is denied by the security manager + * or this is a constructor for {@code java.lang.Class} + * + */ + @Override + @CallerSensitive + public final void setAccessible(boolean flag) { + AccessibleObject.checkPermission(); + if (flag) { + checkCanSetAccessible(Reflection.getCallerClass()); + } + setAccessible0(flag); + } + + @Override + void checkCanSetAccessible(Class caller) { + checkCanSetAccessible(caller, clazz); + if (clazz == Class.class) { + // can we change this to InaccessibleObjectException? + throw new SecurityException("Cannot make a java.lang.Class" + + " constructor accessible"); + } + } + + /** + * Returns the {@code Class} object representing the class that + * declares the constructor represented by this object. + */ + @Override + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of this constructor, as a string. This is + * the binary name of the constructor's declaring class. + */ + @Override + public String getName() { + return getDeclaringClass().getName(); + } + + /** + * {@inheritDoc} + * @jls 8.8.3 Constructor Modifiers + */ + @Override + public int getModifiers() { + return modifiers; + } + + /** + * {@inheritDoc} + * @jls X.X.X MemberPattern Modifiers + */ + @Override + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + @Override + public Annotation[][] getParameterAnnotations() { + return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); + } + + byte[] getRawParameterAnnotations() { + return parameterAnnotations; + } + + /** + * {@inheritDoc} + */ + @Override + public Class[] getParameterTypes() { + return parameterTypes.length == 0 ? parameterTypes : parameterTypes.clone(); + } + + /** + * {@inheritDoc} + * @since 1.8 + */ + public int getParameterCount() { return parameterTypes.length; } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericParameterTypes() { + return super.getGenericParameterTypes(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class[] getExceptionTypes() { + return exceptionTypes.length == 0 ? exceptionTypes : exceptionTypes.clone(); + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + */ + @Override + public Type[] getGenericExceptionTypes() { + return super.getGenericExceptionTypes(); + } + + /** + * Returns an array of arrays of {@code Annotation}s that + * represent the annotations on the bindings, in + * declaration order, of the {@code MemberPattern} represented by + * this object. + * + * @return an array of arrays that represent the annotations on + * the bindings, in declaration order, of + * the member pattern 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; + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @since 1.5 + */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeVariable>[] getTypeParameters() { + if (getSignature() != null) { + return (TypeVariable>[])getGenericInfo().getTypeParameters(); + } else + return (TypeVariable>[])GenericDeclRepository.EMPTY_TYPE_VARS; + } + + + + /** + * Returns a string describing this {@code MemberPattern}, + * including type parameters. The string is formatted as the + * constructor access modifiers, if any, followed by an + * angle-bracketed comma separated list of the constructor's type + * parameters, if any, including informative bounds of the + * type parameters, if any, followed by the fully-qualified name of the + * declaring class, followed by a parenthesized, comma-separated + * list of the {@code MemberPattern}'s generic formal parameter types. + * + * If this constructor was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or class name. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the constructor is declared to throw + * exceptions, the parameter list is followed by a space, followed + * by the word "{@code throws}" followed by a + * comma-separated list of the generic thrown exception types. + * + *

The only possible modifiers for constructors are the access + * modifiers {@code public}, {@code protected} or + * {@code private}. Only one of these may appear, or none if the + * constructor has default (package) access. + * + * @return a string describing this {@code MemberPattern}, + * include type parameters + * + * @since 1.5 + * @jls 8.8.3 Constructor Modifiers + * @jls 8.9.2 Enum Body Declarations + */ + @Override + public String toGenericString() { + return sharedToGenericString(Modifier.constructorModifiers(), false); + } + + String getSignature() { + return signature; + } + + @Override + byte[] getAnnotationBytes() { + return annotations; + } + + @Override + boolean hasGenericInformation() { + return false; + } + + ExecutableRepository getGenericInfo() { + var genericInfo = this.genericInfo; + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = + ExecutableRepository.make(getSignature(), + getFactory()); + this.genericInfo = genericInfo; + } + return genericInfo; //return cached repository + } + + @Override + void specificToStringHeader(StringBuilder sb) { + sb.append(getDeclaringClass().getTypeName()); + } + + @Override + void specificToGenericStringHeader(StringBuilder sb) { + specificToStringHeader(sb); + } + + + String sharedToGenericString(int modifierMask, boolean isDefault) { + try { + StringBuilder sb = new StringBuilder(); + + printModifiersIfNonzero(sb, modifierMask, isDefault); + + sb.append("pattern "); + TypeVariable[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + sb.append(Arrays.stream(typeparms) + .map(Executable::typeVarBounds) + .collect(Collectors.joining(",", "<", "> "))); + } + + specificToGenericStringHeader(sb); + + sb.append('('); + StringJoiner sj = new StringJoiner(","); + Type[] params = Arrays.stream(getPatternBindings()).map(pb -> pb.getGenericType()).toArray(Type[]::new); + for (int j = 0; j < params.length; j++) { + String param = params[j].getTypeName(); + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + param = param.replaceFirst("\\[\\]$", "..."); + sj.add(param); + } + sb.append(sj.toString()); + sb.append(')'); + + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Returns the pattern bindings of {@code MemberPattern}. + * + * @return pattern bindings + */ + public PatternBinding[] getPatternBindings() { + return patternBindings.toArray(PatternBinding[]::new); + } + + /** + * Returns the pattern flags of {@code MemberPattern}. + * + * @return pattern bindings + */ + public int getPatternFlags() { + return patternFlags; + } + + /** + * Initiate pattern matching of this {@code MemberPattern} on the designated {@code matchCandidate}. + * + * @param matchCandidate the match candidate to perform pattern matching over. + * + * @return an array object created as a result of pattern matching + * + * @throws IllegalAccessException if this {@code MemberPattern} object + * is enforcing Java language access control and the underlying + * constructor is inaccessible. + * @throws MatchException if the pattern matching provoked + * by this {@code MemberPattern} fails. + */ + public Object[] invoke(Object matchCandidate) + throws IllegalAccessException, MatchException + { + String underlyingName = getMangledName(); + + try { + Method method = getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass()); + method.setAccessible(override); + return (Object[])Carriers.boxedComponentValueArray( + MethodType.methodType( + Object.class, + Arrays.stream(this.getPatternBindings()) + .map(PatternBinding::getType) + .toArray(Class[]::new) + ) + ).invoke( + method.invoke(matchCandidate, matchCandidate) + ); + } catch (Throwable e) { + throw new MatchException(e.getMessage(), e); + } + } + + byte[] getRawAnnotations() { + return annotations; + } + + /** + * {@inheritDoc} + * + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public T getAnnotation(Class annotationClass) { + return super.getAnnotation(annotationClass); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + @Override + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); + } + + @Override + public AnnotatedType getAnnotatedReturnType() { + return null; + } + + String getMangledName() { + return mangle(this.getDeclaringClass(), Arrays.stream(getPatternBindings()).map(pb -> pb.getType()).toArray(Class[]::new)); + } +} diff --git a/src/java.base/share/classes/java/lang/reflect/PatternBinding.java b/src/java.base/share/classes/java/lang/reflect/PatternBinding.java index 93678d9de72..8c993e95859 100644 --- a/src/java.base/share/classes/java/lang/reflect/PatternBinding.java +++ b/src/java.base/share/classes/java/lang/reflect/PatternBinding.java @@ -44,13 +44,13 @@ * A {@code PatternBinding} provides information about, and dynamic access to, * an initialized binding of a deconstructor. * - * @see Deconstructor#getPatternBindings() () - * @see Deconstructor + * @see MemberPattern#getPatternBindings() () + * @see MemberPattern * @since 23 */ public final class PatternBinding implements AnnotatedElement { // declaring class - private Deconstructor declaringDeconstructor; + private MemberPattern declaringDeconstructor; private String name; private Class type; private String signature; @@ -76,7 +76,7 @@ public final class PatternBinding implements AnnotatedElement { * @param typeAnnotations x * */ - public PatternBinding(Deconstructor declaringDeconstructor, + public PatternBinding(MemberPattern declaringDeconstructor, String name, Class type, String signature, @@ -252,7 +252,7 @@ public Annotation[] getAnnotations() { * * @return The deconstructor declaring this pattern binding. */ - public Deconstructor getDeclaringDeconstructor() { + public MemberPattern getDeclaringDeconstructor() { return declaringDeconstructor; } } diff --git a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java index c253cb96092..673a5b26e8d 100644 --- a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java +++ b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java @@ -28,6 +28,8 @@ import jdk.internal.reflect.MethodAccessor; import jdk.internal.reflect.ConstructorAccessor; +import java.util.ArrayList; + /** Package-private class implementing the jdk.internal.access.JavaLangReflectAccess interface, allowing the java.lang package to instantiate objects in this package. */ @@ -52,6 +54,23 @@ public Constructor newConstructor(Class declaringClass, parameterAnnotations); } + public Deconstructor newDeconstructor(Class declaringClass, + int modifiers, + int patternFlags, + int slot, + ArrayList patternBindings, + String signature, + byte[] annotations) + { + return new Deconstructor<>(declaringClass, + modifiers, + patternFlags, + slot, + patternBindings, + signature, + annotations); + } + public MethodAccessor getMethodAccessor(Method m) { return m.getMethodAccessor(); } @@ -100,7 +119,7 @@ public Class[] getExecutableSharedExceptionTypes(Executable ex) { // // Copying routines, needed to quickly fabricate new Field, - // Method, and Constructor objects from templates + // Method, Constructor and Deconstructor objects from templates // public Method copyMethod(Method arg) { return arg.copy(); @@ -117,6 +136,10 @@ public Constructor copyConstructor(Constructor arg) { return arg.copy(); } + public Deconstructor copyDeconstructor(Deconstructor arg) { + return arg.copy(); + } + @SuppressWarnings("unchecked") public T getRoot(T obj) { return (T) obj.getRoot(); @@ -133,7 +156,7 @@ public T newInstance(Constructor ctor, Object[] args, Class caller) } @Override - public String getMangledName(Deconstructor d) { + public String getMangledName(MemberPattern d) { return d.getMangledName(); } } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java index 6e964584c4a..34a600591a2 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangReflectAccess.java @@ -106,5 +106,5 @@ public void setConstructorAccessor(Constructor c, public T newInstance(Constructor ctor, Object[] args, Class caller) throws IllegalAccessException, InstantiationException, InvocationTargetException; - public String getMangledName(Deconstructor d); + public String getMangledName(MemberPattern d); } diff --git a/src/java.base/share/classes/sun/reflect/generics/scope/DeconstructorScope.java b/src/java.base/share/classes/sun/reflect/generics/scope/MemberPatternScope.java similarity index 78% rename from src/java.base/share/classes/sun/reflect/generics/scope/DeconstructorScope.java rename to src/java.base/share/classes/sun/reflect/generics/scope/MemberPatternScope.java index 3bde6ca5b93..b3cf47e7868 100644 --- a/src/java.base/share/classes/sun/reflect/generics/scope/DeconstructorScope.java +++ b/src/java.base/share/classes/sun/reflect/generics/scope/MemberPatternScope.java @@ -25,18 +25,16 @@ package sun.reflect.generics.scope; -import java.lang.reflect.Constructor; -import java.lang.reflect.Deconstructor; - +import java.lang.reflect.MemberPattern; /** * This class represents the scope containing the type variables of - * a deconstructor. + * a member pattern. */ -public class DeconstructorScope extends AbstractScope> { +public class MemberPatternScope extends AbstractScope> { // constructor is private to enforce use of factory method - private DeconstructorScope(Deconstructor c){ + private MemberPatternScope(MemberPattern c){ super(c); } @@ -51,18 +49,18 @@ private Class getEnclosingClass(){ * @return the enclosing scope */ protected Scope computeEnclosingScope() { - // the enclosing scope of a (generic) constructor is the scope of the + // the enclosing scope of a (generic) member pattern is the scope of the // class in which it was declared. return ClassScope.make(getEnclosingClass()); } /** - * Factory method. Takes a {@code Constructor} object and creates a + * Factory method. Takes a {@code MemberPattern} object and creates a * scope for it. - * @param c - A Constructor whose scope we want to obtain + * @param c - A member pattern whose scope we want to obtain * @return The type-variable scope for the constructor m */ - public static DeconstructorScope make(Deconstructor c) { - return new DeconstructorScope(c); + public static MemberPatternScope make(MemberPattern c) { + return new MemberPatternScope(c); } }