< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodType.java

Print this page




  82  * The query methods {@code parameterArray} and {@code parameterList}
  83  * also provide a choice between arrays and lists.
  84  * <p>
  85  * {@code MethodType} objects are sometimes derived from bytecode instructions
  86  * such as {@code invokedynamic}, specifically from the type descriptor strings associated
  87  * with the instructions in a class file's constant pool.
  88  * <p>
  89  * Like classes and strings, method types can also be represented directly
  90  * in a class file's constant pool as constants.
  91  * A method type may be loaded by an {@code ldc} instruction which refers
  92  * to a suitable {@code CONSTANT_MethodType} constant pool entry.
  93  * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
  94  * (For full details on method type constants, see sections {@jvms
  95  * 4.4.8} and {@jvms 5.4.3.5} of the Java Virtual Machine
  96  * Specification.)
  97  * <p>
  98  * When the JVM materializes a {@code MethodType} from a descriptor string,
  99  * all classes named in the descriptor must be accessible, and will be loaded.
 100  * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
 101  * This loading may occur at any time before the {@code MethodType} object is first derived.

 102  * @author John Rose, JSR 292 EG
 103  * @since 1.7
 104  */
 105 public final
 106 class MethodType
 107         implements Constable,
 108                    TypeDescriptor.OfMethod<Class<?>, MethodType>,
 109                    java.io.Serializable {
 110     @java.io.Serial
 111     private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
 112 
 113     // The rtype and ptypes fields define the structural identity of the method type:
 114     private final @Stable Class<?>   rtype;
 115     private final @Stable Class<?>[] ptypes;
 116 
 117     // The remaining fields are caches of various sorts:
 118     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
 119     private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
 120     private @Stable Invokers invokers;   // cache of handy higher-order adapters
 121     private @Stable String methodDescriptor;  // cache for toMethodDescriptorString


1122      * IMPORTANT: This method is preferable for JDK internal use as it more
1123      * correctly interprets {@code null} ClassLoader than
1124      * {@link #fromMethodDescriptorString(String, ClassLoader)}.
1125      * Use of this method also avoids early initialization issues when system
1126      * ClassLoader is not initialized yet.
1127      */
1128     static MethodType fromDescriptor(String descriptor, ClassLoader loader)
1129         throws IllegalArgumentException, TypeNotPresentException
1130     {
1131         if (!descriptor.startsWith("(") ||  // also generates NPE if needed
1132             descriptor.indexOf(')') < 0 ||
1133             descriptor.indexOf('.') >= 0)
1134             throw newIllegalArgumentException("not a method descriptor: "+descriptor);
1135         List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
1136         Class<?> rtype = types.remove(types.size() - 1);
1137         Class<?>[] ptypes = listToArray(types);
1138         return makeImpl(rtype, ptypes, true);
1139     }
1140 
1141     /**
1142      * Produces a bytecode descriptor representation of the method type.


1143      * <p>
1144      * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
1145      * Two distinct classes which share a common name but have different class loaders
1146      * will appear identical when viewed within descriptor strings.
1147      * <p>
1148      * This method is included for the benefit of applications that must
1149      * generate bytecodes that process method handles and {@code invokedynamic}.
1150      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
1151      * because the latter requires a suitable class loader argument.
1152      * @return the bytecode type descriptor representation

1153      */
1154     public String toMethodDescriptorString() {
1155         String desc = methodDescriptor;
1156         if (desc == null) {
1157             desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
1158             methodDescriptor = desc;
1159         }
1160         return desc;
1161     }
1162 
1163     /**
1164      * Return a field type descriptor string for this type






1165      *
1166      * @return the descriptor string
1167      * @jvms 4.3.2 Field Descriptors









1168      * @since 12

1169      */
1170     @Override
1171     public String descriptorString() {
1172         return toMethodDescriptorString();
1173     }
1174 
1175     /*non-public*/
1176     static String toFieldDescriptorString(Class<?> cls) {
1177         return BytecodeDescriptor.unparse(cls);
1178     }
1179 
1180     /**
1181      * Return a nominal descriptor for this instance, if one can be
1182      * constructed, or an empty {@link Optional} if one cannot be.
1183      *




1184      * @return An {@link Optional} containing the resulting nominal descriptor,
1185      * or an empty {@link Optional} if one cannot be constructed.
1186      * @since 12
1187      */
1188     @Override
1189     public Optional<MethodTypeDesc> describeConstable() {
1190         try {
1191             return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
1192                                                  Stream.of(parameterArray())
1193                                                       .map(p -> p.describeConstable().orElseThrow())
1194                                                       .toArray(ClassDesc[]::new)));
1195         }
1196         catch (NoSuchElementException e) {
1197             return Optional.empty();
1198         }
1199     }
1200 
1201     /// Serialization.
1202 
1203     /**




  82  * The query methods {@code parameterArray} and {@code parameterList}
  83  * also provide a choice between arrays and lists.
  84  * <p>
  85  * {@code MethodType} objects are sometimes derived from bytecode instructions
  86  * such as {@code invokedynamic}, specifically from the type descriptor strings associated
  87  * with the instructions in a class file's constant pool.
  88  * <p>
  89  * Like classes and strings, method types can also be represented directly
  90  * in a class file's constant pool as constants.
  91  * A method type may be loaded by an {@code ldc} instruction which refers
  92  * to a suitable {@code CONSTANT_MethodType} constant pool entry.
  93  * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
  94  * (For full details on method type constants, see sections {@jvms
  95  * 4.4.8} and {@jvms 5.4.3.5} of the Java Virtual Machine
  96  * Specification.)
  97  * <p>
  98  * When the JVM materializes a {@code MethodType} from a descriptor string,
  99  * all classes named in the descriptor must be accessible, and will be loaded.
 100  * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
 101  * This loading may occur at any time before the {@code MethodType} object is first derived.
 102  *
 103  * @author John Rose, JSR 292 EG
 104  * @since 1.7
 105  */
 106 public final
 107 class MethodType
 108         implements Constable,
 109                    TypeDescriptor.OfMethod<Class<?>, MethodType>,
 110                    java.io.Serializable {
 111     @java.io.Serial
 112     private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
 113 
 114     // The rtype and ptypes fields define the structural identity of the method type:
 115     private final @Stable Class<?>   rtype;
 116     private final @Stable Class<?>[] ptypes;
 117 
 118     // The remaining fields are caches of various sorts:
 119     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
 120     private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
 121     private @Stable Invokers invokers;   // cache of handy higher-order adapters
 122     private @Stable String methodDescriptor;  // cache for toMethodDescriptorString


1123      * IMPORTANT: This method is preferable for JDK internal use as it more
1124      * correctly interprets {@code null} ClassLoader than
1125      * {@link #fromMethodDescriptorString(String, ClassLoader)}.
1126      * Use of this method also avoids early initialization issues when system
1127      * ClassLoader is not initialized yet.
1128      */
1129     static MethodType fromDescriptor(String descriptor, ClassLoader loader)
1130         throws IllegalArgumentException, TypeNotPresentException
1131     {
1132         if (!descriptor.startsWith("(") ||  // also generates NPE if needed
1133             descriptor.indexOf(')') < 0 ||
1134             descriptor.indexOf('.') >= 0)
1135             throw newIllegalArgumentException("not a method descriptor: "+descriptor);
1136         List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
1137         Class<?> rtype = types.remove(types.size() - 1);
1138         Class<?>[] ptypes = listToArray(types);
1139         return makeImpl(rtype, ptypes, true);
1140     }
1141 
1142     /**
1143      * Returns a descriptor string for the method type.  This method
1144      * is equivalent to calling {@link #descriptorString() MethodType::descriptorString}.
1145      *
1146      * <p>
1147      * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
1148      * Two distinct classes which share a common name but have different class loaders
1149      * will appear identical when viewed within descriptor strings.
1150      * <p>
1151      * This method is included for the benefit of applications that must
1152      * generate bytecodes that process method handles and {@code invokedynamic}.
1153      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
1154      * because the latter requires a suitable class loader argument.
1155      * @return the descriptor string for this method type
1156      * @jvms 4.3.3 Method Descriptors
1157      */
1158     public String toMethodDescriptorString() {
1159         String desc = methodDescriptor;
1160         if (desc == null) {
1161             desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
1162             methodDescriptor = desc;
1163         }
1164         return desc;
1165     }
1166 
1167     /**
1168      * Returns a descriptor string for this method type.
1169      *
1170      * <p> If none of the parameter types and return type is a {@linkplain Class#isHidden()
1171      * hidden} class or interface, then the result is a method type descriptor string
1172      * (JVMS {@jvms 4.3.3}). {@link MethodTypeDesc MethodTypeDesc} can be created from
1173      * the result method type descriptor via
1174      * {@link MethodTypeDesc#ofDescriptor(String) MethodTypeDesc::ofDescriptor}.
1175      *
1176      * <p> If any of the parameter types and return type is a {@linkplain Class#isHidden()
1177      * hidden} class or interface, then the result is a string of the form:
1178      *    {@code "(<parameter-descriptors>)<return-descriptor>"}
1179      * where {@code <parameter-descriptors>} is the concatenation of the
1180      * {@linkplain Class#descriptorString() descriptor string} of all parameter types
1181      * and the {@linkplain Class#descriptorString() descriptor string} of the return type.
1182      * This method type cannot be described nominally and no
1183      * {@link java.lang.constant.MethodTypeDesc MethodTypeDesc} can be produced from
1184      * the result string.
1185      *
1186      * @return the descriptor string for this method type
1187      * @since 12
1188      * @jvms 4.3.3 Method Descriptors
1189      */
1190     @Override
1191     public String descriptorString() {
1192         return toMethodDescriptorString();
1193     }
1194 
1195     /*non-public*/
1196     static String toFieldDescriptorString(Class<?> cls) {
1197         return BytecodeDescriptor.unparse(cls);
1198     }
1199 
1200     /**
1201      * Returns a nominal descriptor for this instance, if one can be
1202      * constructed, or an empty {@link Optional} if one cannot be.
1203      *
1204      * <p> If any of the parameter types and return type is {@linkplain Class#isHidden()
1205      * hidden}, then this method returns an empty {@link Optional} because
1206      * this method type cannot be described in nominal form.
1207      *
1208      * @return An {@link Optional} containing the resulting nominal descriptor,
1209      * or an empty {@link Optional} if one cannot be constructed.
1210      * @since 12
1211      */
1212     @Override
1213     public Optional<MethodTypeDesc> describeConstable() {
1214         try {
1215             return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
1216                                                  Stream.of(parameterArray())
1217                                                       .map(p -> p.describeConstable().orElseThrow())
1218                                                       .toArray(ClassDesc[]::new)));
1219         }
1220         catch (NoSuchElementException e) {
1221             return Optional.empty();
1222         }
1223     }
1224 
1225     /// Serialization.
1226 
1227     /**


< prev index next >