87 * Like classes and strings, method types can also be represented directly
88 * in a class file's constant pool as constants.
89 * A method type may be loaded by an {@code ldc} instruction which refers
90 * to a suitable {@code CONSTANT_MethodType} constant pool entry.
91 * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
92 * (For full details on method type constants,
93 * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
94 * <p>
95 * When the JVM materializes a {@code MethodType} from a descriptor string,
96 * all classes named in the descriptor must be accessible, and will be loaded.
97 * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
98 * This loading may occur at any time before the {@code MethodType} object is first derived.
99 * @author John Rose, JSR 292 EG
100 * @since 1.7
101 */
102 public final
103 class MethodType
104 implements Constable,
105 TypeDescriptor.OfMethod<Class<?>, MethodType>,
106 java.io.Serializable {
107 private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
108
109 // The rtype and ptypes fields define the structural identity of the method type:
110 private final @Stable Class<?> rtype;
111 private final @Stable Class<?>[] ptypes;
112
113 // The remaining fields are caches of various sorts:
114 private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
115 private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version
116 private @Stable Invokers invokers; // cache of handy higher-order adapters
117 private @Stable String methodDescriptor; // cache for toMethodDescriptorString
118
119 /**
120 * Constructor that performs no copying or validation.
121 * Should only be called from the factory method makeImpl
122 */
123 private MethodType(Class<?> rtype, Class<?>[] ptypes) {
124 this.rtype = rtype;
125 this.ptypes = ptypes;
126 }
1212 * @since 12
1213 */
1214 @Override
1215 public Optional<MethodTypeDesc> describeConstable() {
1216 try {
1217 return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
1218 Stream.of(parameterArray())
1219 .map(p -> p.describeConstable().orElseThrow())
1220 .toArray(ClassDesc[]::new)));
1221 }
1222 catch (NoSuchElementException e) {
1223 return Optional.empty();
1224 }
1225 }
1226
1227 /// Serialization.
1228
1229 /**
1230 * There are no serializable fields for {@code MethodType}.
1231 */
1232 private static final java.io.ObjectStreamField[] serialPersistentFields = { };
1233
1234 /**
1235 * Save the {@code MethodType} instance to a stream.
1236 *
1237 * @serialData
1238 * For portability, the serialized format does not refer to named fields.
1239 * Instead, the return type and parameter type arrays are written directly
1240 * from the {@code writeObject} method, using two calls to {@code s.writeObject}
1241 * as follows:
1242 * <blockquote><pre>{@code
1243 s.writeObject(this.returnType());
1244 s.writeObject(this.parameterArray());
1245 * }</pre></blockquote>
1246 * <p>
1247 * The deserialized field values are checked as if they were
1248 * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
1249 * For example, null values, or {@code void} parameter types,
1250 * will lead to exceptions during deserialization.
1251 * @param s the stream to write the object to
1252 * @throws java.io.IOException if there is a problem writing the object
1253 */
1254 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
1255 s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
1256 s.writeObject(returnType());
1257 s.writeObject(parameterArray());
1258 }
1259
1260 /**
1261 * Reconstitute the {@code MethodType} instance from a stream (that is,
1262 * deserialize it).
1263 * This instance is a scratch object with bogus final fields.
1264 * It provides the parameters to the factory method called by
1265 * {@link #readResolve readResolve}.
1266 * After that call it is discarded.
1267 * @param s the stream to read the object from
1268 * @throws java.io.IOException if there is a problem reading the object
1269 * @throws ClassNotFoundException if one of the component classes cannot be resolved
1270 * @see #readResolve
1271 * @see #writeObject
1272 */
1273 private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
1274 // Assign temporary defaults in case this object escapes
1275 MethodType_init(void.class, NO_PTYPES);
1276
1277 s.defaultReadObject(); // requires serialPersistentFields to be an empty array
1278
1279 Class<?> returnType = (Class<?>) s.readObject();
1280 Class<?>[] parameterArray = (Class<?>[]) s.readObject();
1281 parameterArray = parameterArray.clone(); // make sure it is unshared
1282
1283 // Assign deserialized values
1284 MethodType_init(returnType, parameterArray);
1285 }
1286
1287 // Initialization of state for deserialization only
1288 private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
1289 // In order to communicate these values to readResolve, we must
1290 // store them into the implementation-specific final fields.
1291 checkRtype(rtype);
1292 checkPtypes(ptypes);
1293 UNSAFE.putReference(this, OffsetHolder.rtypeOffset, rtype);
1294 UNSAFE.putReference(this, OffsetHolder.ptypesOffset, ptypes);
1295 }
1296
1297 // Support for resetting final fields while deserializing. Implement Holder
1298 // pattern to make the rarely needed offset calculation lazy.
1299 private static class OffsetHolder {
1300 static final long rtypeOffset
1301 = UNSAFE.objectFieldOffset(MethodType.class, "rtype");
1302
1303 static final long ptypesOffset
1304 = UNSAFE.objectFieldOffset(MethodType.class, "ptypes");
1305 }
1306
1307 /**
1308 * Resolves and initializes a {@code MethodType} object
1309 * after serialization.
1310 * @return the fully initialized {@code MethodType} object
1311 */
1312 private Object readResolve() {
1313 // Do not use a trusted path for deserialization:
1314 // return makeImpl(rtype, ptypes, true);
1315 // Verify all operands, and make sure ptypes is unshared:
1316 try {
1317 return methodType(rtype, ptypes);
1318 } finally {
1319 // Re-assign defaults in case this object escapes
1320 MethodType_init(void.class, NO_PTYPES);
1321 }
1322 }
1323
1324 /**
1325 * Simple implementation of weak concurrent intern set.
1326 *
1327 * @param <T> interned type
1328 */
1329 private static class ConcurrentWeakInternSet<T> {
1330
1331 private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
|
87 * Like classes and strings, method types can also be represented directly
88 * in a class file's constant pool as constants.
89 * A method type may be loaded by an {@code ldc} instruction which refers
90 * to a suitable {@code CONSTANT_MethodType} constant pool entry.
91 * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
92 * (For full details on method type constants,
93 * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
94 * <p>
95 * When the JVM materializes a {@code MethodType} from a descriptor string,
96 * all classes named in the descriptor must be accessible, and will be loaded.
97 * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
98 * This loading may occur at any time before the {@code MethodType} object is first derived.
99 * @author John Rose, JSR 292 EG
100 * @since 1.7
101 */
102 public final
103 class MethodType
104 implements Constable,
105 TypeDescriptor.OfMethod<Class<?>, MethodType>,
106 java.io.Serializable {
107 @java.io.Serial
108 private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
109
110 // The rtype and ptypes fields define the structural identity of the method type:
111 private final @Stable Class<?> rtype;
112 private final @Stable Class<?>[] ptypes;
113
114 // The remaining fields are caches of various sorts:
115 private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
116 private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version
117 private @Stable Invokers invokers; // cache of handy higher-order adapters
118 private @Stable String methodDescriptor; // cache for toMethodDescriptorString
119
120 /**
121 * Constructor that performs no copying or validation.
122 * Should only be called from the factory method makeImpl
123 */
124 private MethodType(Class<?> rtype, Class<?>[] ptypes) {
125 this.rtype = rtype;
126 this.ptypes = ptypes;
127 }
1213 * @since 12
1214 */
1215 @Override
1216 public Optional<MethodTypeDesc> describeConstable() {
1217 try {
1218 return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
1219 Stream.of(parameterArray())
1220 .map(p -> p.describeConstable().orElseThrow())
1221 .toArray(ClassDesc[]::new)));
1222 }
1223 catch (NoSuchElementException e) {
1224 return Optional.empty();
1225 }
1226 }
1227
1228 /// Serialization.
1229
1230 /**
1231 * There are no serializable fields for {@code MethodType}.
1232 */
1233 @java.io.Serial
1234 private static final java.io.ObjectStreamField[] serialPersistentFields = { };
1235
1236 /**
1237 * Save the {@code MethodType} instance to a stream.
1238 *
1239 * @serialData
1240 * For portability, the serialized format does not refer to named fields.
1241 * Instead, the return type and parameter type arrays are written directly
1242 * from the {@code writeObject} method, using two calls to {@code s.writeObject}
1243 * as follows:
1244 * <blockquote><pre>{@code
1245 s.writeObject(this.returnType());
1246 s.writeObject(this.parameterArray());
1247 * }</pre></blockquote>
1248 * <p>
1249 * The deserialized field values are checked as if they were
1250 * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
1251 * For example, null values, or {@code void} parameter types,
1252 * will lead to exceptions during deserialization.
1253 * @param s the stream to write the object to
1254 * @throws java.io.IOException if there is a problem writing the object
1255 */
1256 @java.io.Serial
1257 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
1258 s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
1259 s.writeObject(returnType());
1260 s.writeObject(parameterArray());
1261 }
1262
1263 /**
1264 * Reconstitute the {@code MethodType} instance from a stream (that is,
1265 * deserialize it).
1266 * This instance is a scratch object with bogus final fields.
1267 * It provides the parameters to the factory method called by
1268 * {@link #readResolve readResolve}.
1269 * After that call it is discarded.
1270 * @param s the stream to read the object from
1271 * @throws java.io.IOException if there is a problem reading the object
1272 * @throws ClassNotFoundException if one of the component classes cannot be resolved
1273 * @see #readResolve
1274 * @see #writeObject
1275 */
1276 @java.io.Serial
1277 private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
1278 // Assign temporary defaults in case this object escapes
1279 MethodType_init(void.class, NO_PTYPES);
1280
1281 s.defaultReadObject(); // requires serialPersistentFields to be an empty array
1282
1283 Class<?> returnType = (Class<?>) s.readObject();
1284 Class<?>[] parameterArray = (Class<?>[]) s.readObject();
1285 parameterArray = parameterArray.clone(); // make sure it is unshared
1286
1287 // Assign deserialized values
1288 MethodType_init(returnType, parameterArray);
1289 }
1290
1291 // Initialization of state for deserialization only
1292 private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
1293 // In order to communicate these values to readResolve, we must
1294 // store them into the implementation-specific final fields.
1295 checkRtype(rtype);
1296 checkPtypes(ptypes);
1297 UNSAFE.putReference(this, OffsetHolder.rtypeOffset, rtype);
1298 UNSAFE.putReference(this, OffsetHolder.ptypesOffset, ptypes);
1299 }
1300
1301 // Support for resetting final fields while deserializing. Implement Holder
1302 // pattern to make the rarely needed offset calculation lazy.
1303 private static class OffsetHolder {
1304 static final long rtypeOffset
1305 = UNSAFE.objectFieldOffset(MethodType.class, "rtype");
1306
1307 static final long ptypesOffset
1308 = UNSAFE.objectFieldOffset(MethodType.class, "ptypes");
1309 }
1310
1311 /**
1312 * Resolves and initializes a {@code MethodType} object
1313 * after serialization.
1314 * @return the fully initialized {@code MethodType} object
1315 */
1316 @java.io.Serial
1317 private Object readResolve() {
1318 // Do not use a trusted path for deserialization:
1319 // return makeImpl(rtype, ptypes, true);
1320 // Verify all operands, and make sure ptypes is unshared:
1321 try {
1322 return methodType(rtype, ptypes);
1323 } finally {
1324 // Re-assign defaults in case this object escapes
1325 MethodType_init(void.class, NO_PTYPES);
1326 }
1327 }
1328
1329 /**
1330 * Simple implementation of weak concurrent intern set.
1331 *
1332 * @param <T> interned type
1333 */
1334 private static class ConcurrentWeakInternSet<T> {
1335
1336 private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
|