< prev index next > src/java.base/share/classes/java/lang/invoke/MethodType.java
Print this page
import java.lang.constant.MethodTypeDesc;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Arrays;
+ import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Supplier;
+ import java.util.HashMap;
+ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Stream;
+ import jdk.internal.misc.CDS;
import jdk.internal.util.ReferencedKeySet;
import jdk.internal.util.ReferenceKey;
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.BytecodeDescriptor;
import sun.invoke.util.VerifyType;
private @Stable Object wrapAlt; // alternative wrapped/unwrapped version and
// private communication for readObject and readResolve
private @Stable Invokers invokers; // cache of handy higher-order adapters
private @Stable String methodDescriptor; // cache for toMethodDescriptorString
+ private final boolean checkArchivable = CDS.isDumpingArchive();
/**
* Constructor that performs no copying or validation.
* Should only be called from the factory method makeImpl
*/
private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+ if (checkArchivable) {
+ MethodHandleNatives.checkArchivable(rtype);
+ for (var p : ptypes) {
+ MethodHandleNatives.checkArchivable(p);
+ }
+ }
+
this.rtype = rtype;
this.ptypes = ptypes;
}
/*trusted*/ MethodTypeForm form() { return form; }
}
});
static final Class<?>[] NO_PTYPES = {};
+ private static Object[] archivedObjects;
+
+ private static @Stable HashMap<MethodType,MethodType> archivedMethodTypes;
+
+ private static @Stable MethodType[] objectOnlyTypes;
+
+ @SuppressWarnings("unchecked")
+ static void doit() {
+ CDS.initializeFromArchive(MethodType.class);
+ if (archivedObjects != null) {
+ archivedMethodTypes = (HashMap<MethodType,MethodType>)archivedObjects[0];
+ objectOnlyTypes = (MethodType[])archivedObjects[1];
+ } else {
+ objectOnlyTypes = new MethodType[20];
+ }
+ }
+ static {
+ doit();
+ }
+
/**
* Finds or creates an instance of the given method type.
* @param rtype the return type
* @param ptypes the parameter types
* @return a method type with the given components
private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
if (ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true;
}
MethodType primordialMT = new MethodType(rtype, ptypes);
+ if (archivedMethodTypes != null) {
+ MethodType mt = archivedMethodTypes.get(primordialMT);
+ if (mt != null) {
+ return mt;
+ }
+ }
+
MethodType mt = internTable.get(primordialMT);
if (mt != null)
return mt;
// promote the object to the Real Thing, and reprobe
mt = new MethodType(rtype, ptypes);
}
mt.form = MethodTypeForm.findForm(mt);
return internTable.intern(mt);
}
- private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
/**
* Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* All parameters and the return type will be {@code Object},
// Return a new validated MethodType for the rtype and ptypes passed from readObject.
MethodType mt = ((MethodType[])wrapAlt)[0];
wrapAlt = null;
return mt;
}
+
+ static HashMap<MethodType,MethodType> archive(Archiver archiver) {
+ HashMap<MethodType,MethodType> archivedSet = new HashMap<>();
+
+ for (Iterator<MethodType> i = internTable.iterator(); i.hasNext(); ) {
+ MethodType t = i.next();
+ MethodType a = archiver.clean(t);
+ if (a != null) {
+ archivedSet.put(a, a);
+ }
+ }
+
+ return archivedSet;
+ }
+
+ static class Archiver {
+ ArrayList<MethodType> archived = new ArrayList<>();
+
+ MethodType clean(MethodType t) {
+ if (t == null || t.form == null) { // HACK!
+ return null;
+ }
+ if (archived.contains(t)) {
+ return t;
+ }
+
+ archived.add(t);
+ return t;
+ }
+ }
+
+ // This is called from C code.
+ static void dumpSharedArchive() {
+ Archiver archiver = new Archiver();
+
+ MethodType[] objectOnlyTypesCopy = new MethodType[objectOnlyTypes.length];
+ for (int i = 0; i < objectOnlyTypes.length; i++) {
+ MethodType t = archiver.clean(objectOnlyTypes[i]);
+ if (t != null) {
+ objectOnlyTypesCopy[i] = t;
+ }
+ }
+
+ archivedObjects = new Object[2];
+ archivedObjects[0] = archive(archiver);
+ archivedObjects[1] = objectOnlyTypesCopy;
+
+ DirectMethodHandle.dumpSharedArchive();
+ LambdaForm.NamedFunction.dumpSharedArchive();
+ }
}
< prev index next >