< prev index next >

src/java.base/share/classes/jdk/internal/reflect/MethodHandleAccessorFactory.java

Print this page

  1 /*
  2  * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.reflect;
 27 
 28 import java.lang.invoke.MethodHandle;
 29 import java.lang.invoke.MethodHandles;
 30 import java.lang.invoke.MethodType;
 31 import java.lang.invoke.VarHandle;
 32 import java.lang.reflect.Constructor;
 33 import java.lang.reflect.Executable;
 34 import java.lang.reflect.Field;
 35 import java.lang.reflect.Method;
 36 import java.lang.reflect.Modifier;
 37 
 38 import jdk.internal.access.JavaLangInvokeAccess;
 39 import jdk.internal.access.SharedSecrets;
 40 import jdk.internal.misc.Unsafe;
 41 import jdk.internal.misc.VM;

 42 
 43 import static java.lang.invoke.MethodType.genericMethodType;
 44 import static java.lang.invoke.MethodType.methodType;
 45 import static jdk.internal.reflect.MethodHandleAccessorFactory.LazyStaticHolder.*;
 46 
 47 final class MethodHandleAccessorFactory {
 48     /**
 49      * Creates a MethodAccessor for the given reflected method.
 50      *
 51      * If the given method is called before the java.lang.invoke initialization
 52      * or the given method is a native method, it will use the native VM reflection
 53      * support.
 54      *
 55      * If the given method is a caller-sensitive method and the corresponding
 56      * caller-sensitive adapter with the caller class parameter is present,
 57      * it will use the method handle of the caller-sensitive adapter.
 58      *
 59      * Otherwise, it will use the direct method handle of the given method.
 60      *
 61      * @see CallerSensitive

100 
101         // ExceptionInInitializerError may be thrown during class initialization
102         // Ensure class initialized outside the invocation of method handle
103         // so that EIIE is propagated (not wrapped with ITE)
104         ensureClassInitialized(ctor.getDeclaringClass());
105         try {
106             MethodHandle target = makeConstructorHandle(JLIA.unreflectConstructor(ctor));
107             return DirectConstructorHandleAccessor.constructorAccessor(ctor, target);
108         } catch (IllegalAccessException e) {
109             throw new InternalError(e);
110         }
111     }
112 
113     /**
114      * Creates a ConstructorAccessor that is capable of creating instances
115      * of the given class and instantiated by the given constructor.
116      *
117      * @param decl the class to instantiate
118      * @param ctor the constructor to call
119      * @return an accessible constructor




120      */
121     static ConstructorAccessorImpl newSerializableConstructorAccessor(Class<?> decl, Constructor<?> ctor) {
122         if (!constructorInSuperclass(decl, ctor)) {
123             throw new UnsupportedOperationException(ctor + " not a superclass of " + decl.getName());
124         }
125 
126         // ExceptionInInitializerError may be thrown during class initialization
127         // Ensure class initialized outside the invocation of method handle
128         // so that EIIE is propagated (not wrapped with ITE)
129         ensureClassInitialized(decl);
130         try {
131             MethodHandle target = makeConstructorHandle(JLIA.serializableConstructor(decl, ctor));
132             return DirectConstructorHandleAccessor.constructorAccessor(ctor, target);
133         } catch (IllegalAccessException e) {
134             throw new InternalError(e);
135         }
136     }
137 
138     private static boolean constructorInSuperclass(Class<?> decl, Constructor<?> ctor) {




139         if (decl == ctor.getDeclaringClass())
140             return true;


141 
142         Class<?> cl = decl;
143         while ((cl = cl.getSuperclass()) != null) {





144             if (cl == ctor.getDeclaringClass()) {
145                 return true;
146             }
147         }
148         return false;
149     }
150 
151     private static MethodHandle makeConstructorHandle(MethodHandle ctor) {
152         int paramCount = ctor.type().parameterCount();
153         MethodHandle target = ctor.asFixedArity();
154         MethodType mtype = specializedMethodTypeForConstructor(paramCount);
155         if (paramCount > SPECIALIZED_PARAM_COUNT) {
156             // spread the parameters only for the non-specialized case
157             target = target.asSpreader(Object[].class, paramCount);
158         }
159         return target.asType(mtype);
160     }
161 
162     /**
163      * Creates a FieldAccessor for the given reflected field.
164      *
165      * Limitation: Field access via core reflection is only supported after
166      * java.lang.invoke completes initialization.
167      * java.lang.invoke initialization starts soon after System::initPhase1
168      * and method handles are ready for use when initPhase2 begins.

  1 /*
  2  * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.reflect;
 27 
 28 import java.lang.invoke.MethodHandle;
 29 import java.lang.invoke.MethodHandles;
 30 import java.lang.invoke.MethodType;
 31 import java.lang.invoke.VarHandle;
 32 import java.lang.reflect.Constructor;
 33 import java.lang.reflect.Executable;
 34 import java.lang.reflect.Field;
 35 import java.lang.reflect.Method;
 36 import java.lang.reflect.Modifier;
 37 
 38 import jdk.internal.access.JavaLangInvokeAccess;
 39 import jdk.internal.access.SharedSecrets;
 40 import jdk.internal.misc.Unsafe;
 41 import jdk.internal.misc.VM;
 42 import jdk.internal.value.ValueClass;
 43 
 44 import static java.lang.invoke.MethodType.genericMethodType;
 45 import static java.lang.invoke.MethodType.methodType;
 46 import static jdk.internal.reflect.MethodHandleAccessorFactory.LazyStaticHolder.*;
 47 
 48 final class MethodHandleAccessorFactory {
 49     /**
 50      * Creates a MethodAccessor for the given reflected method.
 51      *
 52      * If the given method is called before the java.lang.invoke initialization
 53      * or the given method is a native method, it will use the native VM reflection
 54      * support.
 55      *
 56      * If the given method is a caller-sensitive method and the corresponding
 57      * caller-sensitive adapter with the caller class parameter is present,
 58      * it will use the method handle of the caller-sensitive adapter.
 59      *
 60      * Otherwise, it will use the direct method handle of the given method.
 61      *
 62      * @see CallerSensitive

101 
102         // ExceptionInInitializerError may be thrown during class initialization
103         // Ensure class initialized outside the invocation of method handle
104         // so that EIIE is propagated (not wrapped with ITE)
105         ensureClassInitialized(ctor.getDeclaringClass());
106         try {
107             MethodHandle target = makeConstructorHandle(JLIA.unreflectConstructor(ctor));
108             return DirectConstructorHandleAccessor.constructorAccessor(ctor, target);
109         } catch (IllegalAccessException e) {
110             throw new InternalError(e);
111         }
112     }
113 
114     /**
115      * Creates a ConstructorAccessor that is capable of creating instances
116      * of the given class and instantiated by the given constructor.
117      *
118      * @param decl the class to instantiate
119      * @param ctor the constructor to call
120      * @return an accessible constructor
121      * @throws UnsupportedOperationException if the constructor is not from
122      *         a superclass, if the instantiated class is a value class, or if
123      *         any superclass between the declaring class of the constructor and
124      *         the instantiated class declares a strict instance field
125      */
126     static ConstructorAccessorImpl newSerializableConstructorAccessor(Class<?> decl, Constructor<?> ctor) {
127         validateSerializableConstructor(decl, ctor);


128 
129         // ExceptionInInitializerError may be thrown during class initialization
130         // Ensure class initialized outside the invocation of method handle
131         // so that EIIE is propagated (not wrapped with ITE)
132         ensureClassInitialized(decl);
133         try {
134             MethodHandle target = makeConstructorHandle(JLIA.serializableConstructor(decl, ctor));
135             return DirectConstructorHandleAccessor.constructorAccessor(ctor, target);
136         } catch (IllegalAccessException e) {
137             throw new InternalError(e);
138         }
139     }
140 
141     /// Ensures a constructor is a valid super constructor to call for the serializable class {@code decl}
142     /// according to the serialization specification.
143     /// 1. The initialized class must not be a concrete value class (the superclasses may be abstract value)
144     /// 2. There should be no strict field initialization skipped by the constructor
145     private static void validateSerializableConstructor(Class<?> decl, Constructor<?> ctor) {
146         if (decl == ctor.getDeclaringClass())
147             throw new UnsupportedOperationException("Attempt to duplicate " + ctor);
148         if (decl.isValue())
149             throw new UnsupportedOperationException("Cannot generate serialization constructor for value class " + decl.getTypeName());
150 
151         Class<?> cl = decl;
152         do {
153             if (ValueClass.hasStrictInstanceField(cl)) {
154                 throw new UnsupportedOperationException("Class " + cl.getTypeName() + " between " + ctor + " and "
155                         + decl.getTypeName() + " declares a strictly-initialized instance field");
156             }
157             cl = cl.getSuperclass();
158             if (cl == ctor.getDeclaringClass()) {
159                 return;
160             }
161         } while (cl != null);
162         throw new UnsupportedOperationException(ctor + " not a superclass of " + decl.getName());
163     }
164 
165     private static MethodHandle makeConstructorHandle(MethodHandle ctor) {
166         int paramCount = ctor.type().parameterCount();
167         MethodHandle target = ctor.asFixedArity();
168         MethodType mtype = specializedMethodTypeForConstructor(paramCount);
169         if (paramCount > SPECIALIZED_PARAM_COUNT) {
170             // spread the parameters only for the non-specialized case
171             target = target.asSpreader(Object[].class, paramCount);
172         }
173         return target.asType(mtype);
174     }
175 
176     /**
177      * Creates a FieldAccessor for the given reflected field.
178      *
179      * Limitation: Field access via core reflection is only supported after
180      * java.lang.invoke completes initialization.
181      * java.lang.invoke initialization starts soon after System::initPhase1
182      * and method handles are ready for use when initPhase2 begins.
< prev index next >