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 valid type 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 in nominal form:
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 valid type descriptor string.</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 string (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
|