8272347: ObjectMethods::bootstrap should specify NPE if any argument except lookup is null
Reviewed-by: mchung, chegar
This commit is contained in:
parent
7fc8540907
commit
0609421d4b
@ -37,6 +37,8 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap methods for state-driven implementations of core methods,
|
* Bootstrap methods for state-driven implementations of core methods,
|
||||||
* including {@link Object#equals(Object)}, {@link Object#hashCode()}, and
|
* including {@link Object#equals(Object)}, {@link Object#hashCode()}, and
|
||||||
@ -317,22 +319,31 @@ public class ObjectMethods {
|
|||||||
* @param recordClass the record class hosting the record components
|
* @param recordClass the record class hosting the record components
|
||||||
* @param names the list of component names, joined into a string
|
* @param names the list of component names, joined into a string
|
||||||
* separated by ";", or the empty string if there are no
|
* separated by ";", or the empty string if there are no
|
||||||
* components. Maybe be null, if the {@code methodName}
|
* components. This parameter is ignored if the {@code methodName}
|
||||||
* is {@code "equals"} or {@code "hashCode"}.
|
* parameter is {@code "equals"} or {@code "hashCode"}
|
||||||
* @param getters method handles for the accessor methods for the components
|
* @param getters method handles for the accessor methods for the components
|
||||||
* @return a call site if invoked by indy, or a method handle
|
* @return a call site if invoked by indy, or a method handle
|
||||||
* if invoked by a condy
|
* if invoked by a condy
|
||||||
* @throws IllegalArgumentException if the bootstrap arguments are invalid
|
* @throws IllegalArgumentException if the bootstrap arguments are invalid
|
||||||
* or inconsistent
|
* or inconsistent
|
||||||
|
* @throws NullPointerException if any argument but {@code lookup} is {@code null},
|
||||||
|
* in the case of the {@code getters} argument, its
|
||||||
|
* contents cannot be {@code null} either
|
||||||
* @throws Throwable if any exception is thrown during call site construction
|
* @throws Throwable if any exception is thrown during call site construction
|
||||||
*/
|
*/
|
||||||
public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type,
|
public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type,
|
||||||
Class<?> recordClass,
|
Class<?> recordClass,
|
||||||
String names,
|
String names,
|
||||||
MethodHandle... getters) throws Throwable {
|
MethodHandle... getters) throws Throwable {
|
||||||
|
requireNonNull(methodName);
|
||||||
|
requireNonNull(type);
|
||||||
|
requireNonNull(recordClass);
|
||||||
|
requireNonNull(names);
|
||||||
|
requireNonNull(getters);
|
||||||
|
Arrays.stream(getters).forEach(Objects::requireNonNull);
|
||||||
MethodType methodType;
|
MethodType methodType;
|
||||||
if (type instanceof MethodType)
|
if (type instanceof MethodType mt)
|
||||||
methodType = (MethodType) type;
|
methodType = mt;
|
||||||
else {
|
else {
|
||||||
methodType = null;
|
methodType = null;
|
||||||
if (!MethodHandle.class.equals(type))
|
if (!MethodHandle.class.equals(type))
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
* @run testng/othervm/java.security.policy=empty.policy ObjectMethodsTest
|
* @run testng/othervm/java.security.policy=empty.policy ObjectMethodsTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.lang.invoke.CallSite;
|
import java.lang.invoke.CallSite;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@ -103,7 +104,7 @@ public class ObjectMethodsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testHashCodeC() throws Throwable {
|
public void testHashCodeC() throws Throwable {
|
||||||
CallSite cs = (CallSite)ObjectMethods.bootstrap(LOOKUP, "hashCode", C.HASHCODE_DESC, C.class, null, C.ACCESSORS);
|
CallSite cs = (CallSite)ObjectMethods.bootstrap(LOOKUP, "hashCode", C.HASHCODE_DESC, C.class, "x;y", C.ACCESSORS);
|
||||||
MethodHandle handle = cs.dynamicInvoker();
|
MethodHandle handle = cs.dynamicInvoker();
|
||||||
C c = new C(6, 7);
|
C c = new C(6, 7);
|
||||||
int hc = (int)handle.invokeExact(c);
|
int hc = (int)handle.invokeExact(c);
|
||||||
@ -151,15 +152,21 @@ public class ObjectMethodsTest {
|
|||||||
assertThrows(IAE, () -> ObjectMethods.bootstrap(LOOKUP, "hashCode", C.TO_STRING_DESC, C.class, "x;y", C.ACCESSORS));
|
assertThrows(IAE, () -> ObjectMethods.bootstrap(LOOKUP, "hashCode", C.TO_STRING_DESC, C.class, "x;y", C.ACCESSORS));
|
||||||
assertThrows(IAE, () -> ObjectMethods.bootstrap(LOOKUP, "equals", C.HASHCODE_DESC, C.class, "x;y", C.ACCESSORS));
|
assertThrows(IAE, () -> ObjectMethods.bootstrap(LOOKUP, "equals", C.HASHCODE_DESC, C.class, "x;y", C.ACCESSORS));
|
||||||
|
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "toString", C.TO_STRING_DESC, C.class, "x;y", null) );
|
record NamePlusType(String mn, MethodType mt) {}
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "toString", C.TO_STRING_DESC, C.class, null, C.ACCESSORS));
|
List<NamePlusType> namePlusTypeList = List.of(
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "toString", C.TO_STRING_DESC, null, "x;y", C.ACCESSORS));
|
new NamePlusType("toString", C.TO_STRING_DESC),
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "equals", C.EQUALS_DESC, null, "x;y", C.ACCESSORS));
|
new NamePlusType("equals", C.EQUALS_DESC),
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "hashCode", C.HASHCODE_DESC, null, "x;y", C.ACCESSORS));
|
new NamePlusType("hashCode", C.HASHCODE_DESC)
|
||||||
|
);
|
||||||
|
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, "toString", null, C.class, "x;y", C.ACCESSORS));
|
for (NamePlusType npt : namePlusTypeList) {
|
||||||
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, null, C.TO_STRING_DESC, C.class, "x;y", C.ACCESSORS));
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), C.class, "x;y", null));
|
||||||
//assertThrows(NPE, () -> ObjectMethods.bootstrap(null, "toString", C.TO_STRING_DESC, C.class, "x;y", C.ACCESSORS));
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), C.class, "x;y", new MethodHandle[]{null}));
|
||||||
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), C.class, null, C.ACCESSORS));
|
||||||
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), null, "x;y", C.ACCESSORS));
|
||||||
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), null, C.class, "x;y", C.ACCESSORS));
|
||||||
|
assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, null, npt.mt(), C.class, "x;y", C.ACCESSORS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on the ObjectMethods internal implementation
|
// Based on the ObjectMethods internal implementation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user