8300924: Method::invoke throws wrong exception type when passing wrong number of arguments to method with 4 or more parameters
Reviewed-by: rriggs
This commit is contained in:
parent
49ff52087b
commit
7aaf76c529
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,23 +44,18 @@ class DirectConstructorHandleAccessor extends ConstructorAccessorImpl {
|
||||
return new NativeAccessor(ctor);
|
||||
}
|
||||
|
||||
private static final int PARAM_COUNT_MASK = 0x00FF;
|
||||
private static final int NONZERO_BIT = 0x8000_0000;
|
||||
|
||||
private final int paramFlags;
|
||||
private final int paramCount;
|
||||
private final MethodHandle target;
|
||||
|
||||
DirectConstructorHandleAccessor(Constructor<?> ctor, MethodHandle target) {
|
||||
this.paramFlags = (ctor.getParameterCount() & PARAM_COUNT_MASK) | NONZERO_BIT;
|
||||
this.paramCount = ctor.getParameterCount();
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance(Object[] args) throws InstantiationException, InvocationTargetException {
|
||||
int argc = args != null ? args.length : 0;
|
||||
// only check argument count for specialized forms
|
||||
int paramCount = paramFlags & PARAM_COUNT_MASK;
|
||||
if (paramCount <= SPECIALIZED_PARAM_COUNT && argc != paramCount) {
|
||||
if (argc != paramCount) {
|
||||
throw new IllegalArgumentException("wrong number of arguments: " + argc + " expected: " + paramCount);
|
||||
}
|
||||
try {
|
||||
@ -87,7 +82,7 @@ class DirectConstructorHandleAccessor extends ConstructorAccessorImpl {
|
||||
@Hidden
|
||||
@ForceInline
|
||||
Object invokeImpl(Object[] args) throws Throwable {
|
||||
return switch (paramFlags & PARAM_COUNT_MASK) {
|
||||
return switch (paramCount) {
|
||||
case 0 -> target.invokeExact();
|
||||
case 1 -> target.invokeExact(args[0]);
|
||||
case 2 -> target.invokeExact(args[0], args[1]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,7 +39,6 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import static java.lang.invoke.MethodType.genericMethodType;
|
||||
import static jdk.internal.reflect.MethodHandleAccessorFactory.SPECIALIZED_PARAM_COUNT;
|
||||
import static jdk.internal.reflect.MethodHandleAccessorFactory.LazyStaticHolder.JLIA;
|
||||
|
||||
class DirectMethodHandleAccessor extends MethodAccessorImpl {
|
||||
@ -329,9 +328,6 @@ class DirectMethodHandleAccessor extends MethodAccessorImpl {
|
||||
}
|
||||
|
||||
private static void checkArgumentCount(int paramCount, Object[] args) {
|
||||
// only check argument count for specialized forms
|
||||
if (paramCount > SPECIALIZED_PARAM_COUNT) return;
|
||||
|
||||
int argc = args != null ? args.length : 0;
|
||||
if (argc != paramCount) {
|
||||
throw new IllegalArgumentException("wrong number of arguments: " + argc + " expected: " + paramCount);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8271820
|
||||
* @bug 8271820 8300924
|
||||
* @modules java.base/jdk.internal.reflect
|
||||
* @summary Test compliance of ConstructorAccessor, FieldAccessor, MethodAccessor implementations
|
||||
* @run testng/othervm --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED -Djdk.reflect.useDirectMethodHandle=true -XX:-ShowCodeDetailsInExceptionMessages MethodHandleAccessorsTest
|
||||
@ -55,6 +55,8 @@ import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MethodHandleAccessorsTest {
|
||||
static final boolean newImpl = Boolean.getBoolean("jdk.reflect.useDirectMethodHandle");
|
||||
|
||||
|
||||
public static void public_static_V() {}
|
||||
|
||||
@ -68,6 +70,12 @@ public class MethodHandleAccessorsTest {
|
||||
|
||||
public static int public_static_I_I(int i) { return i; }
|
||||
|
||||
public static void public_static_V_L3(Object o1, Object o2, Object o3) { }
|
||||
|
||||
public static void public_static_V_L4(Object o1, Object o2, Object o3, Object o4) { }
|
||||
|
||||
public static void public_V_L5(Object o1, Object o2, Object o3, Object o4, Object o5) { }
|
||||
|
||||
public void public_I_V(int i) {}
|
||||
|
||||
public int public_I_I(int i) { return i; }
|
||||
@ -146,6 +154,14 @@ public class MethodHandleAccessorsTest {
|
||||
this(varargs_object(first, rest));
|
||||
}
|
||||
|
||||
public Public(Object o1, Object o2, Object o3) {
|
||||
this("3-arg constructor");
|
||||
}
|
||||
|
||||
public Public(Object o1, Object o2, Object o3, Object o4) {
|
||||
this("4-arg constructor");
|
||||
}
|
||||
|
||||
public Public(RuntimeException exc) {
|
||||
throw exc;
|
||||
}
|
||||
@ -405,6 +421,10 @@ public class MethodHandleAccessorsTest {
|
||||
private static final Throwable[] wrong_argument_count_no_details = new Throwable[] {
|
||||
new IllegalArgumentException("wrong number of arguments")
|
||||
};
|
||||
|
||||
private static final Throwable[] wrong_argument_count_zero_args = new Throwable[] {
|
||||
new IllegalArgumentException("wrong number of arguments: 0 expected:")
|
||||
};
|
||||
private static final Throwable[] wrong_argument_count = new Throwable[] {
|
||||
new IllegalArgumentException("wrong number of arguments"),
|
||||
new IllegalArgumentException("array is not of length 1")
|
||||
@ -462,7 +482,6 @@ public class MethodHandleAccessorsTest {
|
||||
private Object[][] testOneArgMethods() {
|
||||
MethodHandleAccessorsTest inst = new MethodHandleAccessorsTest();
|
||||
Object wrongInst = new Object();
|
||||
boolean newImpl = Boolean.getBoolean("jdk.reflect.useDirectMethodHandle");
|
||||
return new Object[][]{
|
||||
new Object[] {"public_static_I_V", int.class, null, new Object[]{12}, null, noException},
|
||||
new Object[] {"public_static_I_I", int.class, null, new Object[]{12}, 12, noException},
|
||||
@ -493,6 +512,27 @@ public class MethodHandleAccessorsTest {
|
||||
};
|
||||
}
|
||||
|
||||
@DataProvider(name = "testMultiArgMethods")
|
||||
private Object[][] testMultiArgMethods() {
|
||||
MethodHandleAccessorsTest inst = new MethodHandleAccessorsTest();
|
||||
Class<?>[] params_L3 = new Class<?>[] { Object.class, Object.class, Object.class};
|
||||
Class<?>[] params_L4 = new Class<?>[] { Object.class, Object.class, Object.class, Object.class};
|
||||
Class<?>[] params_L5 = new Class<?>[] { Object.class, Object.class, Object.class, Object.class, Object.class};
|
||||
|
||||
return new Object[][]{
|
||||
new Object[]{"public_static_V_L3", params_L3, null, new Object[3], null, noException},
|
||||
new Object[]{"public_static_V_L4", params_L4, null, new Object[4], null, noException},
|
||||
new Object[]{"public_V_L5", params_L5, inst, new Object[5], null, noException},
|
||||
// wrong arguments
|
||||
new Object[]{"public_static_V_L3", params_L3, null, null, null,
|
||||
newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details},
|
||||
new Object[]{"public_static_V_L4", params_L4, null, new Object[0], null,
|
||||
newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details},
|
||||
new Object[]{"public_V_L5", params_L5, inst, null, null,
|
||||
newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details},
|
||||
};
|
||||
}
|
||||
|
||||
@DataProvider(name = "testMethodsWithVarargs")
|
||||
private Object[][] testMethodsWithVarargs() {
|
||||
Class<?>[] paramTypes = new Class<?>[] { int[].class };
|
||||
@ -523,6 +563,12 @@ public class MethodHandleAccessorsTest {
|
||||
doTest(MethodHandleAccessorsTest.class.getDeclaredMethod(methodname, paramType), target, args, expectedReturn, expectedExpections);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "testMultiArgMethods")
|
||||
public void testMultiArgMethod(String methodname, Class<?>[] paramTypes, Object target, Object[] args,
|
||||
Object expectedReturn, Throwable[] expectedExpections) throws Exception {
|
||||
doTest(MethodHandleAccessorsTest.class.getDeclaredMethod(methodname, paramTypes), target, args, expectedReturn, expectedExpections);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "testMethodsWithVarargs")
|
||||
public void testMethodsWithVarargs(String methodname, Class<?>[] paramTypes, Object target, Object[] args,
|
||||
Object expectedReturn, Throwable[] expectedExpections) throws Exception {
|
||||
@ -561,6 +607,26 @@ public class MethodHandleAccessorsTest {
|
||||
doTest(Public.class.getDeclaredConstructor(paramTypes), args, expectedReturn, expectedExpections);
|
||||
}
|
||||
|
||||
@DataProvider(name = "testMultiArgConstructors")
|
||||
private Object[][] testMultiArgConstructors() {
|
||||
Class<?>[] params_L3 = new Class<?>[] { Object.class, Object.class, Object.class};
|
||||
Class<?>[] params_L4 = new Class<?>[] { Object.class, Object.class, Object.class, Object.class};
|
||||
Object o = "arg";
|
||||
return new Object[][]{
|
||||
new Object[]{params_L3, new Object[3], new Public(o, o, o), noException},
|
||||
new Object[]{params_L4, new Object[4], new Public(o, o, o, o), noException},
|
||||
new Object[]{params_L3, new Object[]{}, null,
|
||||
newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details},
|
||||
new Object[]{params_L4, null, null,
|
||||
newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "testMultiArgConstructors")
|
||||
public void testMultiArgConstructors(Class<?>[] paramTypes, Object[] args, Object expectedReturn, Throwable[] expectedExpections) throws Exception {
|
||||
doTest(Public.class.getDeclaredConstructor(paramTypes), args, expectedReturn, expectedExpections);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherConstructors() throws Exception {
|
||||
doTest(Private.class.getDeclaredConstructor(), new Object[]{}, new Private());
|
||||
|
Loading…
Reference in New Issue
Block a user