< prev index next >

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

Print this page
rev 58769 : [mq]: type-descriptor-name


  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     /**
1204      * There are no serializable fields for {@code MethodType}.
1205      */
1206     @java.io.Serial




  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  * <p>
 103  * <b><a id="descriptor">Nominal Descriptors</a></b>
 104  * <p>
 105  * A {@code MethodType} can be described in {@linkplain MethodTypeDesc nominal form}
 106  * if and only if all of the parameter types and return type can be described
 107  * with a {@link Class#describeConstable() nominal descriptor} represented by
 108  * {@link ClassDesc}.  If a method type can be described norminally, then:
 109  * <ul>
 110  * <li>The method type has a {@link MethodTypeDesc nominal descriptor}
 111  *     returned by {@link #describeConstable() MethodType::describeConstable}.</li>
 112  * <li>The descriptor string returned by
 113  *     {@link #descriptorString() MethodType::descriptorString} or
 114  *     {@link #toMethodDescriptorString() MethodType::toMethodDescriptorString}
 115  *     for the method type is a method descriptor (JVMS {@jvms 4.3.3}).</li>
 116  * </ul>
 117  * <p>
 118  * If any of the parameter types or return type cannot be described
 119  * nominally, i.e. {@link Class#describeConstable() Class::describeConstable}
 120  * returns an empty optional for that type,
 121  * then the method type cannot be described nominally:
 122  * <ul>
 123  * <li>The method type has no {@link MethodTypeDesc nominal descriptor} and
 124  *     {@link #describeConstable() MethodType::describeConstable} returns
 125  *     an empty optional.</li>
 126  * <li>The descriptor string returned by
 127  *     {@link #descriptorString() MethodType::descriptorString} or
 128  *     {@link #toMethodDescriptorString() MethodType::toMethodDescriptorString}
 129  *     for the method type is not a type descriptor.</li>
 130  * </ul>
 131  *
 132  * @author John Rose, JSR 292 EG
 133  * @since 1.7
 134  */
 135 public final
 136 class MethodType
 137         implements Constable,
 138                    TypeDescriptor.OfMethod<Class<?>, MethodType>,
 139                    java.io.Serializable {
 140     @java.io.Serial
 141     private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
 142 
 143     // The rtype and ptypes fields define the structural identity of the method type:
 144     private final @Stable Class<?>   rtype;
 145     private final @Stable Class<?>[] ptypes;
 146 
 147     // The remaining fields are caches of various sorts:
 148     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
 149     private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
 150     private @Stable Invokers invokers;   // cache of handy higher-order adapters
 151     private @Stable String methodDescriptor;  // cache for toMethodDescriptorString


1152      * IMPORTANT: This method is preferable for JDK internal use as it more
1153      * correctly interprets {@code null} ClassLoader than
1154      * {@link #fromMethodDescriptorString(String, ClassLoader)}.
1155      * Use of this method also avoids early initialization issues when system
1156      * ClassLoader is not initialized yet.
1157      */
1158     static MethodType fromDescriptor(String descriptor, ClassLoader loader)
1159         throws IllegalArgumentException, TypeNotPresentException
1160     {
1161         if (!descriptor.startsWith("(") ||  // also generates NPE if needed
1162             descriptor.indexOf(')') < 0 ||
1163             descriptor.indexOf('.') >= 0)
1164             throw newIllegalArgumentException("not a method descriptor: "+descriptor);
1165         List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
1166         Class<?> rtype = types.remove(types.size() - 1);
1167         Class<?>[] ptypes = listToArray(types);
1168         return makeImpl(rtype, ptypes, true);
1169     }
1170 
1171     /**
1172      * Returns a descriptor string for the method type.  This method
1173      * is equivalent to calling {@link #descriptorString() MethodType::descriptorString}.
1174      *
1175      * <p>
1176      * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
1177      * Two distinct classes which share a common name but have different class loaders
1178      * will appear identical when viewed within descriptor strings.
1179      * <p>
1180      * This method is included for the benefit of applications that must
1181      * generate bytecodes that process method handles and {@code invokedynamic}.
1182      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
1183      * because the latter requires a suitable class loader argument.
1184      * @return the descriptor string for this method type
1185      * @jvms 4.3.3 Method Descriptors
1186      * @see <a href="#descriptor">Nominal Descriptor for {@code MethodType}</a>
1187      */
1188     public String toMethodDescriptorString() {
1189         String desc = methodDescriptor;
1190         if (desc == null) {
1191             desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
1192             methodDescriptor = desc;
1193         }
1194         return desc;
1195     }
1196 
1197     /**
1198      * Returns a descriptor string for this method type.
1199      *
1200      * <p>
1201      * If this method type can be <a href="#descriptor">described nominally</a>,
1202      * then the result is a method type descriptor (JVMS {@jvms 4.3.3}).
1203      * {@link MethodTypeDesc MethodTypeDesc} for this method type
1204      * can be produced by calling {@link MethodTypeDesc#ofDescriptor(String)
1205      * MethodTypeDesc::ofDescriptor} with the result descriptor string.
1206      * <p>
1207      * If this method type cannot be <a href="#descriptor">described nominally</a>
1208      * and the result is a string of the form:
1209      * <blockquote>{@code "(<parameter-descriptors>)<return-descriptor>"}</blockquote>
1210      * where {@code <parameter-descriptors>} is the concatenation of the
1211      * {@linkplain Class#descriptorString() descriptor string} of all
1212      * of the parameter types and the {@linkplain Class#descriptorString() descriptor string}
1213      * of the return type. No {@link java.lang.constant.MethodTypeDesc MethodTypeDesc}
1214      * can be produced from the result string.
1215      *
1216      * @return the descriptor string for this method type

1217      * @since 12
1218      * @jvms 4.3.3 Method Descriptors
1219      * @see <a href="#descriptor">Nominal Descriptor for {@code MethodType}</a>
1220      */
1221     @Override
1222     public String descriptorString() {
1223         return toMethodDescriptorString();
1224     }
1225 
1226     /*non-public*/
1227     static String toFieldDescriptorString(Class<?> cls) {
1228         return BytecodeDescriptor.unparse(cls);
1229     }
1230 
1231     /**
1232      * Returns a nominal descriptor for this instance, if one can be
1233      * constructed, or an empty {@link Optional} if one cannot be.
1234      *
1235      * @return An {@link Optional} containing the resulting nominal descriptor,
1236      * or an empty {@link Optional} if one cannot be constructed.
1237      * @since 12
1238      * @see <a href="#descriptor">Nominal Descriptor for {@code MethodType}</a>
1239      */
1240     @Override
1241     public Optional<MethodTypeDesc> describeConstable() {
1242         try {
1243             return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
1244                                                  Stream.of(parameterArray())
1245                                                       .map(p -> p.describeConstable().orElseThrow())
1246                                                       .toArray(ClassDesc[]::new)));
1247         }
1248         catch (NoSuchElementException e) {
1249             return Optional.empty();
1250         }
1251     }
1252 
1253     /// Serialization.
1254 
1255     /**
1256      * There are no serializable fields for {@code MethodType}.
1257      */
1258     @java.io.Serial


< prev index next >