< prev index next >

src/java.base/share/classes/java/lang/runtime/ObjectMethods.java

Print this page

 47  * methods for record classes.
 48  *
 49  * @since 16
 50  */
 51 public class ObjectMethods {
 52 
 53     private ObjectMethods() { }
 54 
 55     private static final int MAX_STRING_CONCAT_SLOTS = 20;
 56 
 57     private static final MethodHandle FALSE = MethodHandles.zero(boolean.class);
 58     private static final MethodHandle TRUE = MethodHandles.constant(boolean.class, true);
 59     private static final MethodHandle ZERO = MethodHandles.zero(int.class);
 60     private static final MethodHandle CLASS_IS_INSTANCE;
 61     private static final MethodHandle OBJECTS_EQUALS;
 62     private static final MethodHandle OBJECTS_HASHCODE;
 63     private static final MethodHandle OBJECTS_TOSTRING;
 64     private static final MethodHandle OBJECT_EQ;
 65     private static final MethodHandle HASH_COMBINER;
 66 
 67     private static final HashMap<Class<?>, MethodHandle> primitiveEquals = new HashMap<>();


 68     private static final HashMap<Class<?>, MethodHandle> primitiveHashers = new HashMap<>();
 69     private static final HashMap<Class<?>, MethodHandle> primitiveToString = new HashMap<>();
 70 
 71     static {
 72         try {
 73             Class<ObjectMethods> OBJECT_METHODS_CLASS = ObjectMethods.class;
 74             MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
 75             MethodHandles.Lookup lookup = MethodHandles.lookup();
 76 
 77             CLASS_IS_INSTANCE = publicLookup.findVirtual(Class.class, "isInstance",
 78                                                          MethodType.methodType(boolean.class, Object.class));
 79             OBJECTS_EQUALS = publicLookup.findStatic(Objects.class, "equals",
 80                                                      MethodType.methodType(boolean.class, Object.class, Object.class));
 81             OBJECTS_HASHCODE = publicLookup.findStatic(Objects.class, "hashCode",
 82                                                        MethodType.methodType(int.class, Object.class));
 83             OBJECTS_TOSTRING = publicLookup.findStatic(Objects.class, "toString",
 84                                                        MethodType.methodType(String.class, Object.class));
 85 
 86             OBJECT_EQ = lookup.findStatic(OBJECT_METHODS_CLASS, "eq",
 87                                           MethodType.methodType(boolean.class, Object.class, Object.class));

374      * @return             a call site if invoked by indy, or a method handle
375      *                     if invoked by a condy
376      * @throws IllegalArgumentException if the bootstrap arguments are invalid
377      *                                  or inconsistent
378      * @throws NullPointerException if any argument is {@code null} or if any element
379      *                              in the {@code getters} array is {@code null}
380      * @throws Throwable if any exception is thrown during call site construction
381      */
382     public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type,
383                                    Class<?> recordClass,
384                                    String names,
385                                    MethodHandle... getters) throws Throwable {
386         requireNonNull(lookup);
387         requireNonNull(methodName);
388         requireNonNull(type);
389         requireNonNull(recordClass);
390         requireNonNull(names);
391         requireNonNull(getters);
392         Arrays.stream(getters).forEach(Objects::requireNonNull);
393         MethodType methodType;
394         if (type instanceof MethodType mt)
395             methodType = mt;
396         else {



397             methodType = null;
398             if (!MethodHandle.class.equals(type))
399                 throw new IllegalArgumentException(type.toString());
400         }
401         List<MethodHandle> getterList = List.of(getters);





402         MethodHandle handle = switch (methodName) {
403             case "equals"   -> {
404                 if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, recordClass, Object.class)))
405                     throw new IllegalArgumentException("Bad method type: " + methodType);
406                 yield makeEquals(recordClass, getterList);
407             }
408             case "hashCode" -> {
409                 if (methodType != null && !methodType.equals(MethodType.methodType(int.class, recordClass)))
410                     throw new IllegalArgumentException("Bad method type: " + methodType);
411                 yield makeHashCode(recordClass, getterList);
412             }
413             case "toString" -> {
414                 if (methodType != null && !methodType.equals(MethodType.methodType(String.class, recordClass)))
415                     throw new IllegalArgumentException("Bad method type: " + methodType);
416                 List<String> nameList = "".equals(names) ? List.of() : List.of(names.split(";"));
417                 if (nameList.size() != getterList.size())
418                     throw new IllegalArgumentException("Name list and accessor list do not match");
419                 yield makeToString(lookup, recordClass, getters, nameList);
420             }
421             default -> throw new IllegalArgumentException(methodName);

 47  * methods for record classes.
 48  *
 49  * @since 16
 50  */
 51 public class ObjectMethods {
 52 
 53     private ObjectMethods() { }
 54 
 55     private static final int MAX_STRING_CONCAT_SLOTS = 20;
 56 
 57     private static final MethodHandle FALSE = MethodHandles.zero(boolean.class);
 58     private static final MethodHandle TRUE = MethodHandles.constant(boolean.class, true);
 59     private static final MethodHandle ZERO = MethodHandles.zero(int.class);
 60     private static final MethodHandle CLASS_IS_INSTANCE;
 61     private static final MethodHandle OBJECTS_EQUALS;
 62     private static final MethodHandle OBJECTS_HASHCODE;
 63     private static final MethodHandle OBJECTS_TOSTRING;
 64     private static final MethodHandle OBJECT_EQ;
 65     private static final MethodHandle HASH_COMBINER;
 66 
 67     /* package-private */
 68     static final HashMap<Class<?>, MethodHandle> primitiveEquals = new HashMap<>();
 69 
 70     private static final HashMap<Class<?>, MethodHandle> primitiveHashers = new HashMap<>();
 71     private static final HashMap<Class<?>, MethodHandle> primitiveToString = new HashMap<>();
 72 
 73     static {
 74         try {
 75             Class<ObjectMethods> OBJECT_METHODS_CLASS = ObjectMethods.class;
 76             MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
 77             MethodHandles.Lookup lookup = MethodHandles.lookup();
 78 
 79             CLASS_IS_INSTANCE = publicLookup.findVirtual(Class.class, "isInstance",
 80                                                          MethodType.methodType(boolean.class, Object.class));
 81             OBJECTS_EQUALS = publicLookup.findStatic(Objects.class, "equals",
 82                                                      MethodType.methodType(boolean.class, Object.class, Object.class));
 83             OBJECTS_HASHCODE = publicLookup.findStatic(Objects.class, "hashCode",
 84                                                        MethodType.methodType(int.class, Object.class));
 85             OBJECTS_TOSTRING = publicLookup.findStatic(Objects.class, "toString",
 86                                                        MethodType.methodType(String.class, Object.class));
 87 
 88             OBJECT_EQ = lookup.findStatic(OBJECT_METHODS_CLASS, "eq",
 89                                           MethodType.methodType(boolean.class, Object.class, Object.class));

376      * @return             a call site if invoked by indy, or a method handle
377      *                     if invoked by a condy
378      * @throws IllegalArgumentException if the bootstrap arguments are invalid
379      *                                  or inconsistent
380      * @throws NullPointerException if any argument is {@code null} or if any element
381      *                              in the {@code getters} array is {@code null}
382      * @throws Throwable if any exception is thrown during call site construction
383      */
384     public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type,
385                                    Class<?> recordClass,
386                                    String names,
387                                    MethodHandle... getters) throws Throwable {
388         requireNonNull(lookup);
389         requireNonNull(methodName);
390         requireNonNull(type);
391         requireNonNull(recordClass);
392         requireNonNull(names);
393         requireNonNull(getters);
394         Arrays.stream(getters).forEach(Objects::requireNonNull);
395         MethodType methodType;
396         if (type instanceof MethodType mt) {
397             methodType = mt;
398             if (mt.parameterType(0) != recordClass) {
399                 throw new IllegalArgumentException("Bad method type: " + mt);
400             }
401         } else {
402             methodType = null;
403             if (!MethodHandle.class.equals(type))
404                 throw new IllegalArgumentException(type.toString());
405         }
406         List<MethodHandle> getterList = List.of(getters);
407         for (MethodHandle getter : getterList) {
408             if (getter.type().parameterType(0) != recordClass) {
409                 throw new IllegalArgumentException("Bad receiver type: " + getter);
410             }
411         }
412         MethodHandle handle = switch (methodName) {
413             case "equals"   -> {
414                 if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, recordClass, Object.class)))
415                     throw new IllegalArgumentException("Bad method type: " + methodType);
416                 yield makeEquals(recordClass, getterList);
417             }
418             case "hashCode" -> {
419                 if (methodType != null && !methodType.equals(MethodType.methodType(int.class, recordClass)))
420                     throw new IllegalArgumentException("Bad method type: " + methodType);
421                 yield makeHashCode(recordClass, getterList);
422             }
423             case "toString" -> {
424                 if (methodType != null && !methodType.equals(MethodType.methodType(String.class, recordClass)))
425                     throw new IllegalArgumentException("Bad method type: " + methodType);
426                 List<String> nameList = "".equals(names) ? List.of() : List.of(names.split(";"));
427                 if (nameList.size() != getterList.size())
428                     throw new IllegalArgumentException("Name list and accessor list do not match");
429                 yield makeToString(lookup, recordClass, getters, nameList);
430             }
431             default -> throw new IllegalArgumentException(methodName);
< prev index next >