/* * Copyright (c) 1996, 2017, 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.misc.SharedSecrets; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.ConstructorAccessor; import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.ForceInline; import sun.reflect.annotation.TypeAnnotation; import sun.reflect.annotation.TypeAnnotationParser; import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.factory.CoreReflectionFactory; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.scope.ConstructorScope; import java.lang.annotation.Annotation; import java.lang.annotation.AnnotationFormatError; import java.util.StringJoiner; /** * {@code Constructor} provides information about, and access to, a single * constructor for a class. * *

{@code Constructor} permits widening conversions to occur when matching the * actual parameters to newInstance() with the underlying * constructor's formal parameters, but throws an * {@code IllegalArgumentException} if a narrowing conversion would occur. * * @param the class in which the constructor is declared * * @see Member * @see java.lang.Class * @see java.lang.Class#getConstructors() * @see java.lang.Class#getConstructor(Class[]) * @see java.lang.Class#getDeclaredConstructors() * * @author Kenneth Russell * @author Nakul Saraiya * @since 1.1 */ public final class Constructor extends Executable { private Class clazz; private int slot; private Class[] parameterTypes; private Class[] exceptionTypes; private int modifiers; // Generics and annotations support private transient String signature; // generic info repository; lazily initialized private transient ConstructorRepository genericInfo; private byte[] annotations; private 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() { // lazily initialize repository if necessary if (genericInfo == null) { // create and cache generic info repository genericInfo = ConstructorRepository.make(getSignature(), getFactory()); } return genericInfo; //return cached repository } private volatile ConstructorAccessor constructorAccessor; // For sharing of ConstructorAccessors. This branching structure // is currently only two levels deep (i.e., one root Constructor // and potentially many Constructor objects pointing to it.) // // If this branching structure would ever contain cycles, deadlocks can // occur in annotation code. private Constructor root; /** * Used by Excecutable for annotation sharing. */ @Override Executable getRoot() { return root; } /** * Package-private constructor used by ReflectAccess to enable * instantiation of these objects in Java code from the java.lang * package via sun.reflect.LangReflectAccess. */ Constructor(Class declaringClass, Class[] parameterTypes, Class[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations) { this.clazz = declaringClass; this.parameterTypes = parameterTypes; this.exceptionTypes = checkedExceptions; this.modifiers = modifiers; this.slot = slot; this.signature = signature; this.annotations = annotations; this.parameterAnnotations = parameterAnnotations; } /** * 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 Constructor. */ Constructor copy() { // This routine enables sharing of ConstructorAccessor objects // among Constructor 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"); Constructor res = new Constructor<>(clazz, parameterTypes, exceptionTypes, modifiers, slot, signature, annotations, parameterAnnotations); res.root = this; // Might as well eagerly propagate this if already present res.constructorAccessor = constructorAccessor; return res; } /** * {@inheritDoc} * *

A {@code SecurityException} is also thrown if this object is a * {@code Constructor} 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} * * @spec JPMS */ @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"); } } @Override boolean hasGenericInformation() { return (getSignature() != null); } @Override byte[] getAnnotationBytes() { return annotations; } /** * 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} */ @Override public int getModifiers() { return modifiers; } /** * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @since 1.5 */ @Override @SuppressWarnings({"rawtypes", "unchecked"}) public TypeVariable>[] getTypeParameters() { if (getSignature() != null) { return (TypeVariable>[])getGenericInfo().getTypeParameters(); } else return (TypeVariable>[])new TypeVariable[0]; } @Override Class[] getSharedParameterTypes() { return parameterTypes; } /** * {@inheritDoc} */ @Override public Class[] getParameterTypes() { return 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.clone(); } /** * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @throws TypeNotPresentException {@inheritDoc} * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ @Override public Type[] getGenericExceptionTypes() { return super.getGenericExceptionTypes(); } /** * Compares this {@code Constructor} against the specified object. * Returns true if the objects are the same. Two {@code Constructor} objects are * the same if they were declared by the same class and have the * same formal parameter types. */ public boolean equals(Object obj) { if (obj != null && obj instanceof Constructor) { Constructor other = (Constructor)obj; if (getDeclaringClass() == other.getDeclaringClass()) { return equalParamTypes(parameterTypes, other.parameterTypes); } } return false; } /** * Returns a hashcode for this {@code Constructor}. The hashcode is * the same as the hashcode for the underlying constructor's * declaring class name. */ public int hashCode() { return getDeclaringClass().getName().hashCode(); } /** * Returns a string describing this {@code Constructor}. The string is * formatted as the constructor access modifiers, if any, * followed by the fully-qualified name of the declaring class, * followed by a parenthesized, comma-separated list of the * constructor's formal parameter types. For example: *
{@code
     *    public java.util.Hashtable(int,float)
     * }
* *

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 * 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} * @jls 8.8.3 Constructor Modifiers * @jls 8.9.2 Enum Body Declarations */ public String toString() { return sharedToString(Modifier.constructorModifiers(), false, parameterTypes, exceptionTypes); } @Override void specificToStringHeader(StringBuilder sb) { sb.append(getDeclaringClass().getTypeName()); } @Override String toShortString() { StringBuilder sb = new StringBuilder("constructor "); sb.append(getDeclaringClass().getTypeName()); sb.append('('); StringJoiner sj = new StringJoiner(","); for (Class parameterType : getParameterTypes()) { sj.add(parameterType.getTypeName()); } sb.append(sj); sb.append(')'); return sb.toString(); } /** * Returns a string describing this {@code Constructor}, * 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, 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); } @Override void specificToGenericStringHeader(StringBuilder sb) { specificToStringHeader(sb); } /** * Uses the constructor represented by this {@code Constructor} object to * create and initialize a new instance of the constructor's * declaring class, with the specified initialization parameters. * Individual parameters are automatically unwrapped to match * primitive formal parameters, and both primitive and reference * parameters are subject to method invocation conversions as necessary. * *

If the number of formal parameters required by the underlying constructor * is 0, the supplied {@code initargs} array may be of length 0 or null. * *

If the constructor's declaring class is an inner class in a * non-static context, the first argument to the constructor needs * to be the enclosing instance; see section 15.9.3 of * The Java™ Language Specification. * *

If the required access and argument checks succeed and the * instantiation will proceed, the constructor's declaring class * is initialized if it has not already been initialized. * *

If the constructor completes normally, returns the newly * created and initialized instance. * * @param initargs array of objects to be passed as arguments to * the constructor call; values of primitive types are wrapped in * a wrapper object of the appropriate type (e.g. a {@code float} * in a {@link java.lang.Float Float}) * * @return a new object created by calling the constructor * this object represents * * @exception IllegalAccessException if this {@code Constructor} object * is enforcing Java language access control and the underlying * constructor is inaccessible. * @exception IllegalArgumentException if the number of actual * and formal parameters differ; if an unwrapping * conversion for primitive arguments fails; or if, * after possible unwrapping, a parameter value * cannot be converted to the corresponding formal * parameter type by a method invocation conversion; if * this constructor pertains to an enum type. * @exception InstantiationException if the class that declares the * underlying constructor represents an abstract class. * @exception InvocationTargetException if the underlying constructor * throws an exception. * @exception ExceptionInInitializerError if the initialization provoked * by this method fails. */ @CallerSensitive @ForceInline // to ensure Reflection.getCallerClass optimization public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { Class caller = Reflection.getCallerClass(); checkAccess(caller, clazz, clazz, modifiers); } if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects"); ConstructorAccessor ca = constructorAccessor; // read volatile if (ca == null) { ca = acquireConstructorAccessor(); } @SuppressWarnings("unchecked") T inst = (T) ca.newInstance(initargs); return inst; } /** * {@inheritDoc} * @since 1.5 */ @Override public boolean isVarArgs() { return super.isVarArgs(); } /** * {@inheritDoc} * @jls 13.1 The Form of a Binary * @since 1.5 */ @Override public boolean isSynthetic() { return super.isSynthetic(); } // NOTE that there is no synchronization used here. It is correct // (though not efficient) to generate more than one // ConstructorAccessor for a given Constructor. However, avoiding // synchronization will probably make the implementation more // scalable. private ConstructorAccessor acquireConstructorAccessor() { // First check to see if one has been created yet, and take it // if so. ConstructorAccessor tmp = null; if (root != null) tmp = root.getConstructorAccessor(); if (tmp != null) { constructorAccessor = tmp; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newConstructorAccessor(this); setConstructorAccessor(tmp); } return tmp; } // Returns ConstructorAccessor for this Constructor object, not // looking up the chain to the root ConstructorAccessor getConstructorAccessor() { return constructorAccessor; } // Sets the ConstructorAccessor for this Constructor object and // (recursively) its root void setConstructorAccessor(ConstructorAccessor accessor) { constructorAccessor = accessor; // Propagate up if (root != null) { root.setConstructorAccessor(accessor); } } int getSlot() { return slot; } String getSignature() { return signature; } byte[] getRawAnnotations() { return annotations; } byte[] getRawParameterAnnotations() { return parameterAnnotations; } /** * {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @since 1.5 */ public T getAnnotation(Class annotationClass) { return super.getAnnotation(annotationClass); } /** * {@inheritDoc} * @since 1.5 */ public Annotation[] getDeclaredAnnotations() { return super.getDeclaredAnnotations(); } /** * {@inheritDoc} * @since 1.5 */ @Override public Annotation[][] getParameterAnnotations() { return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); } @Override boolean handleParameterNumberMismatch(int resultLength, int numParameters) { Class declaringClass = getDeclaringClass(); if (declaringClass.isEnum() || declaringClass.isAnonymousClass() || declaringClass.isLocalClass() ) return false; // Can't do reliable parameter counting else { if (declaringClass.isMemberClass() && ((declaringClass.getModifiers() & Modifier.STATIC) == 0) && resultLength + 1 == numParameters) { return true; } else { throw new AnnotationFormatError( "Parameter annotations don't match number of parameters"); } } } /** * {@inheritDoc} * @since 1.8 */ @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getDeclaringClass()); } /** * {@inheritDoc} * @since 1.8 */ @Override public AnnotatedType getAnnotatedReceiverType() { Class thisDeclClass = getDeclaringClass(); Class enclosingClass = thisDeclClass.getEnclosingClass(); if (enclosingClass == null) { // A Constructor for a top-level class return null; } Class outerDeclaringClass = thisDeclClass.getDeclaringClass(); if (outerDeclaringClass == null) { // A constructor for a local or anonymous class return null; } // Either static nested or inner class if (Modifier.isStatic(thisDeclClass.getModifiers())) { // static nested return null; } // A Constructor for an inner class return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), SharedSecrets.getJavaLangAccess(). getConstantPool(thisDeclClass), this, thisDeclClass, enclosingClass, TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } }