author | jrose |
Sat, 30 Oct 2010 21:02:30 -0700 | |
changeset 7554 | 8a0ad9757002 |
parent 7053 | da0e2dc092d3 |
child 7555 | a279ebc3b25c |
permissions | -rw-r--r-- |
4535 | 1 |
/* |
5725 | 2 |
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. |
4535 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
4535 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
4535 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
4535 | 24 |
*/ |
25 |
||
26 |
/* @test |
|
27 |
* @summary unit tests for java.dyn.MethodHandles |
|
28 |
* @compile -XDinvokedynamic MethodHandlesTest.java |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
29 |
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest |
4535 | 30 |
*/ |
31 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
32 |
package test.java.dyn; |
4535 | 33 |
|
34 |
import java.dyn.*; |
|
35 |
import java.dyn.MethodHandles.Lookup; |
|
36 |
import java.lang.reflect.*; |
|
37 |
import java.util.*; |
|
38 |
import org.junit.*; |
|
39 |
import static org.junit.Assert.*; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
40 |
import static org.junit.Assume.*; |
4535 | 41 |
|
42 |
||
43 |
/** |
|
44 |
* |
|
45 |
* @author jrose |
|
46 |
*/ |
|
47 |
public class MethodHandlesTest { |
|
48 |
// How much output? |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
49 |
static int verbosity = 0; |
5726 | 50 |
static { |
51 |
String vstr = System.getProperty("test.java.dyn.MethodHandlesTest.verbosity"); |
|
52 |
if (vstr != null) verbosity = Integer.parseInt(vstr); |
|
53 |
} |
|
4535 | 54 |
|
55 |
// Set this true during development if you want to fast-forward to |
|
56 |
// a particular new, non-working test. Tests which are known to |
|
57 |
// work (or have recently worked) test this flag and return on true. |
|
58 |
static boolean CAN_SKIP_WORKING = false; |
|
59 |
//static { CAN_SKIP_WORKING = true; } |
|
60 |
||
61 |
// Set true to test more calls. If false, some tests are just |
|
62 |
// lookups, without exercising the actual method handle. |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
63 |
static boolean DO_MORE_CALLS = true; |
4535 | 64 |
|
65 |
||
66 |
@Test |
|
67 |
public void testFirst() throws Throwable { |
|
68 |
verbosity += 9; try { |
|
69 |
// left blank for debugging |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
70 |
} finally { printCounts(); verbosity -= 9; } |
4535 | 71 |
} |
72 |
||
4537 | 73 |
// current failures |
74 |
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") |
|
75 |
public void testFail_1() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
76 |
// AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters |
4537 | 77 |
testSpreadArguments(int.class, 0, 6); |
78 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
79 |
@Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args") |
4537 | 80 |
public void testFail_2() throws Throwable { |
81 |
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: |
|
82 |
testSpreadArguments(Object.class, 0, 2); |
|
83 |
} |
|
84 |
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
|
85 |
public void testFail_3() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
86 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 87 |
testSpreadArguments(int.class, 1, 2); |
88 |
} |
|
89 |
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
|
90 |
public void testFail_4() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
91 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 92 |
testCollectArguments(int.class, 1, 2); |
93 |
} |
|
94 |
@Test @Ignore("cannot collect leading primitive types") |
|
95 |
public void testFail_5() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
96 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 97 |
testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class)); |
98 |
} |
|
99 |
@Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") |
|
100 |
public void testFail_6() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
101 |
// ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13 |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
102 |
testInsertArguments(0, 0, MAX_ARG_INCREASE+10); |
4537 | 103 |
} |
4535 | 104 |
static final int MAX_ARG_INCREASE = 3; |
105 |
||
106 |
public MethodHandlesTest() { |
|
107 |
} |
|
108 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
109 |
@Before |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
110 |
public void checkImplementedPlatform() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
111 |
boolean platformOK = false; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
112 |
Properties properties = System.getProperties(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
113 |
String vers = properties.getProperty("java.vm.version"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
114 |
String name = properties.getProperty("java.vm.name"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
115 |
String arch = properties.getProperty("os.arch"); |
5726 | 116 |
if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") || |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
117 |
arch.equals("sparc") || arch.equals("sparcv9")) && |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
118 |
(name.contains("Client") || name.contains("Server")) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
119 |
) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
120 |
platformOK = true; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
121 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
122 |
System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
123 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
124 |
assumeTrue(platformOK); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
125 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
126 |
|
4535 | 127 |
String testName; |
5726 | 128 |
static int allPosTests, allNegTests; |
4535 | 129 |
int posTests, negTests; |
130 |
@After |
|
131 |
public void printCounts() { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
132 |
if (verbosity >= 2 && (posTests | negTests) != 0) { |
4535 | 133 |
System.out.println(); |
134 |
if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); |
|
135 |
if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); |
|
5726 | 136 |
allPosTests += posTests; |
137 |
allNegTests += negTests; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
138 |
posTests = negTests = 0; |
4535 | 139 |
} |
140 |
} |
|
141 |
void countTest(boolean positive) { |
|
142 |
if (positive) ++posTests; |
|
143 |
else ++negTests; |
|
144 |
} |
|
145 |
void countTest() { countTest(true); } |
|
146 |
void startTest(String name) { |
|
147 |
if (testName != null) printCounts(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
148 |
if (verbosity >= 1) |
4535 | 149 |
System.out.println(name); |
150 |
posTests = negTests = 0; |
|
151 |
testName = name; |
|
152 |
} |
|
153 |
||
154 |
@BeforeClass |
|
155 |
public static void setUpClass() throws Exception { |
|
156 |
calledLog.clear(); |
|
157 |
calledLog.add(null); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
158 |
nextArgVal = INITIAL_ARG_VAL; |
4535 | 159 |
} |
160 |
||
161 |
@AfterClass |
|
162 |
public static void tearDownClass() throws Exception { |
|
5726 | 163 |
int posTests = allPosTests, negTests = allNegTests; |
164 |
if (verbosity >= 2 && (posTests | negTests) != 0) { |
|
165 |
System.out.println(); |
|
166 |
if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases"); |
|
167 |
if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases"); |
|
168 |
} |
|
4535 | 169 |
} |
170 |
||
171 |
static List<Object> calledLog = new ArrayList<Object>(); |
|
172 |
static Object logEntry(String name, Object... args) { |
|
173 |
return Arrays.asList(name, Arrays.asList(args)); |
|
174 |
} |
|
175 |
static Object called(String name, Object... args) { |
|
176 |
Object entry = logEntry(name, args); |
|
177 |
calledLog.add(entry); |
|
178 |
return entry; |
|
179 |
} |
|
180 |
static void assertCalled(String name, Object... args) { |
|
181 |
Object expected = logEntry(name, args); |
|
182 |
Object actual = calledLog.get(calledLog.size() - 1); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
183 |
if (expected.equals(actual) && verbosity < 9) return; |
4535 | 184 |
System.out.println("assertCalled "+name+":"); |
185 |
System.out.println("expected: "+expected); |
|
186 |
System.out.println("actual: "+actual); |
|
187 |
System.out.println("ex. types: "+getClasses(expected)); |
|
188 |
System.out.println("act. types: "+getClasses(actual)); |
|
189 |
assertEquals("previous method call", expected, actual); |
|
190 |
} |
|
191 |
static void printCalled(MethodHandle target, String name, Object... args) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
192 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
193 |
System.out.println("calling MH="+target+" to "+name+Arrays.toString(args)); |
4535 | 194 |
} |
195 |
||
196 |
static Object castToWrapper(Object value, Class<?> dst) { |
|
197 |
Object wrap = null; |
|
198 |
if (value instanceof Number) |
|
199 |
wrap = castToWrapperOrNull(((Number)value).longValue(), dst); |
|
200 |
if (value instanceof Character) |
|
201 |
wrap = castToWrapperOrNull((char)(Character)value, dst); |
|
202 |
if (wrap != null) return wrap; |
|
203 |
return dst.cast(value); |
|
204 |
} |
|
205 |
||
206 |
static Object castToWrapperOrNull(long value, Class<?> dst) { |
|
207 |
if (dst == int.class || dst == Integer.class) |
|
208 |
return (int)(value); |
|
209 |
if (dst == long.class || dst == Long.class) |
|
210 |
return (long)(value); |
|
211 |
if (dst == char.class || dst == Character.class) |
|
212 |
return (char)(value); |
|
213 |
if (dst == short.class || dst == Short.class) |
|
214 |
return (short)(value); |
|
215 |
if (dst == float.class || dst == Float.class) |
|
216 |
return (float)(value); |
|
217 |
if (dst == double.class || dst == Double.class) |
|
218 |
return (double)(value); |
|
4537 | 219 |
if (dst == byte.class || dst == Byte.class) |
220 |
return (byte)(value); |
|
221 |
if (dst == boolean.class || dst == boolean.class) |
|
222 |
return ((value % 29) & 1) == 0; |
|
4535 | 223 |
return null; |
224 |
} |
|
225 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
226 |
static final int ONE_MILLION = (1000*1000), // first int value |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
227 |
TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
228 |
INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
229 |
static long nextArgVal; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
230 |
static long nextArg(boolean moreBits) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
231 |
long val = nextArgVal++; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
232 |
long sign = -(val & 1); // alternate signs |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
233 |
val >>= 1; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
234 |
if (moreBits) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
235 |
// Guarantee some bits in the high word. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
236 |
// In any case keep the decimal representation simple-looking, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
237 |
// with lots of zeroes, so as not to make the printed decimal |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
238 |
// strings unnecessarily noisy. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
239 |
val += (val % ONE_MILLION) * TEN_BILLION; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
240 |
return val ^ sign; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
241 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
242 |
static int nextArg() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
243 |
// Produce a 32-bit result something like ONE_MILLION+(smallint). |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
244 |
// Example: 1_000_042. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
245 |
return (int) nextArg(false); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
246 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
247 |
static long nextArg(Class<?> kind) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
248 |
if (kind == long.class || kind == Long.class || |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
249 |
kind == double.class || kind == Double.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
250 |
// produce a 64-bit result something like |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
251 |
// ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
252 |
// Example: 10_000_420_001_000_042. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
253 |
return nextArg(true); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
254 |
return (long) nextArg(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
255 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
256 |
|
4535 | 257 |
static Object randomArg(Class<?> param) { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
258 |
Object wrap = castToWrapperOrNull(nextArg(param), param); |
4535 | 259 |
if (wrap != null) { |
260 |
return wrap; |
|
261 |
} |
|
262 |
// import sun.dyn.util.Wrapper; |
|
263 |
// Wrapper wrap = Wrapper.forBasicType(dst); |
|
264 |
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) |
|
265 |
// wrap = Wrapper.forWrapperType(dst); |
|
266 |
// if (wrap != Wrapper.OBJECT) |
|
267 |
// return wrap.wrap(nextArg++); |
|
7053 | 268 |
if (param.isInterface()) { |
269 |
for (Class<?> c : param.getClasses()) { |
|
270 |
if (param.isAssignableFrom(c) && !c.isInterface()) |
|
271 |
{ param = c; break; } |
|
272 |
} |
|
273 |
} |
|
4535 | 274 |
if (param.isInterface() || param.isAssignableFrom(String.class)) |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
275 |
return "#"+nextArg(); |
4535 | 276 |
else |
277 |
try { |
|
278 |
return param.newInstance(); |
|
279 |
} catch (InstantiationException ex) { |
|
280 |
} catch (IllegalAccessException ex) { |
|
281 |
} |
|
282 |
return null; // random class not Object, String, Integer, etc. |
|
283 |
} |
|
284 |
static Object[] randomArgs(Class<?>... params) { |
|
285 |
Object[] args = new Object[params.length]; |
|
286 |
for (int i = 0; i < args.length; i++) |
|
287 |
args[i] = randomArg(params[i]); |
|
288 |
return args; |
|
289 |
} |
|
290 |
static Object[] randomArgs(int nargs, Class<?> param) { |
|
291 |
Object[] args = new Object[nargs]; |
|
292 |
for (int i = 0; i < args.length; i++) |
|
293 |
args[i] = randomArg(param); |
|
294 |
return args; |
|
295 |
} |
|
296 |
||
297 |
static <T, E extends T> T[] array(Class<T[]> atype, E... a) { |
|
298 |
return Arrays.copyOf(a, a.length, atype); |
|
299 |
} |
|
300 |
static <T> T[] cat(T[] a, T... b) { |
|
301 |
int alen = a.length, blen = b.length; |
|
302 |
if (blen == 0) return a; |
|
303 |
T[] c = Arrays.copyOf(a, alen + blen); |
|
304 |
System.arraycopy(b, 0, c, alen, blen); |
|
305 |
return c; |
|
306 |
} |
|
307 |
static Integer[] boxAll(int... vx) { |
|
308 |
Integer[] res = new Integer[vx.length]; |
|
309 |
for (int i = 0; i < res.length; i++) { |
|
310 |
res[i] = vx[i]; |
|
311 |
} |
|
312 |
return res; |
|
313 |
} |
|
314 |
static Object getClasses(Object x) { |
|
315 |
if (x == null) return x; |
|
316 |
if (x instanceof String) return x; // keep the name |
|
317 |
if (x instanceof List) { |
|
318 |
// recursively report classes of the list elements |
|
319 |
Object[] xa = ((List)x).toArray(); |
|
320 |
for (int i = 0; i < xa.length; i++) |
|
321 |
xa[i] = getClasses(xa[i]); |
|
322 |
return Arrays.asList(xa); |
|
323 |
} |
|
324 |
return x.getClass().getSimpleName(); |
|
325 |
} |
|
326 |
||
327 |
static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) { |
|
328 |
return changeArgTypes(target, 0, 999, argType); |
|
329 |
} |
|
330 |
static MethodHandle changeArgTypes(MethodHandle target, |
|
331 |
int beg, int end, Class<?> argType) { |
|
332 |
MethodType targetType = target.type(); |
|
333 |
end = Math.min(end, targetType.parameterCount()); |
|
334 |
ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList()); |
|
335 |
Collections.fill(argTypes.subList(beg, end), argType); |
|
4537 | 336 |
MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); |
4535 | 337 |
return MethodHandles.convertArguments(target, ttype2); |
338 |
} |
|
339 |
||
340 |
// This lookup is good for all members in and under MethodHandlesTest. |
|
341 |
static final Lookup PRIVATE = MethodHandles.lookup(); |
|
342 |
// This lookup is good for package-private members but not private ones. |
|
343 |
static final Lookup PACKAGE = PackageSibling.lookup(); |
|
344 |
// This lookup is good only for public members. |
|
4537 | 345 |
static final Lookup PUBLIC = MethodHandles.publicLookup(); |
4535 | 346 |
|
347 |
// Subject methods... |
|
348 |
static class Example implements IntExample { |
|
349 |
final String name; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
350 |
public Example() { name = "Example#"+nextArg(); } |
4535 | 351 |
protected Example(String name) { this.name = name; } |
352 |
protected Example(int x) { this(); called("protected <init>", this, x); } |
|
353 |
@Override public String toString() { return name; } |
|
354 |
||
355 |
public void v0() { called("v0", this); } |
|
356 |
void pkg_v0() { called("pkg_v0", this); } |
|
357 |
private void pri_v0() { called("pri_v0", this); } |
|
358 |
public static void s0() { called("s0"); } |
|
359 |
static void pkg_s0() { called("pkg_s0"); } |
|
360 |
private static void pri_s0() { called("pri_s0"); } |
|
361 |
||
362 |
public Object v1(Object x) { return called("v1", this, x); } |
|
363 |
public Object v2(Object x, Object y) { return called("v2", this, x, y); } |
|
364 |
public Object v2(Object x, int y) { return called("v2", this, x, y); } |
|
365 |
public Object v2(int x, Object y) { return called("v2", this, x, y); } |
|
366 |
public Object v2(int x, int y) { return called("v2", this, x, y); } |
|
367 |
public static Object s1(Object x) { return called("s1", x); } |
|
368 |
public static Object s2(int x) { return called("s2", x); } |
|
369 |
public static Object s3(long x) { return called("s3", x); } |
|
370 |
public static Object s4(int x, int y) { return called("s4", x, y); } |
|
371 |
public static Object s5(long x, int y) { return called("s5", x, y); } |
|
372 |
public static Object s6(int x, long y) { return called("s6", x, y); } |
|
373 |
public static Object s7(float x, double y) { return called("s7", x, y); } |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
374 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
375 |
static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial |
4535 | 376 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
377 |
static final Lookup EXAMPLE = Example.EXAMPLE; |
4535 | 378 |
public static class PubExample extends Example { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
379 |
public PubExample() { super("PubExample#"+nextArg()); } |
4535 | 380 |
} |
381 |
static class SubExample extends Example { |
|
382 |
@Override public void v0() { called("Sub/v0", this); } |
|
383 |
@Override void pkg_v0() { called("Sub/pkg_v0", this); } |
|
384 |
private SubExample(int x) { called("<init>", this, x); } |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
385 |
public SubExample() { super("SubExample#"+nextArg()); } |
4535 | 386 |
} |
387 |
public static interface IntExample { |
|
388 |
public void v0(); |
|
7053 | 389 |
public static class Impl implements IntExample { |
4535 | 390 |
public void v0() { called("Int/v0", this); } |
391 |
final String name; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
392 |
public Impl() { name = "Impl#"+nextArg(); } |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
393 |
@Override public String toString() { return name; } |
4535 | 394 |
} |
395 |
} |
|
396 |
||
397 |
static final Object[][][] ACCESS_CASES = { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
398 |
{ { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
399 |
{ { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
400 |
{ { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
401 |
{ { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: all true |
4535 | 402 |
}; |
403 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
404 |
static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
405 |
Object[][] cases; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
406 |
if (name.contains("pri_") || isSpecial) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
407 |
cases = ACCESS_CASES[1]; // PRIVATE only |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
408 |
} else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
409 |
cases = ACCESS_CASES[2]; // not PUBLIC |
4537 | 410 |
} else { |
411 |
assertTrue(name.indexOf('_') < 0); |
|
412 |
boolean pubc = Modifier.isPublic(defc.getModifiers()); |
|
413 |
if (pubc) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
414 |
cases = ACCESS_CASES[3]; // all access levels |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
415 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
416 |
cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC |
4537 | 417 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
418 |
if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
419 |
cases = Arrays.copyOfRange(cases, 0, cases.length-1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
420 |
return cases; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
421 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
422 |
static Object[][] accessCases(Class<?> defc, String name) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
423 |
return accessCases(defc, name, false); |
4535 | 424 |
} |
425 |
||
426 |
@Test |
|
427 |
public void testFindStatic() throws Throwable { |
|
428 |
if (CAN_SKIP_WORKING) return; |
|
429 |
startTest("findStatic"); |
|
430 |
testFindStatic(PubExample.class, void.class, "s0"); |
|
431 |
testFindStatic(Example.class, void.class, "s0"); |
|
432 |
testFindStatic(Example.class, void.class, "pkg_s0"); |
|
433 |
testFindStatic(Example.class, void.class, "pri_s0"); |
|
434 |
||
435 |
testFindStatic(Example.class, Object.class, "s1", Object.class); |
|
436 |
testFindStatic(Example.class, Object.class, "s2", int.class); |
|
437 |
testFindStatic(Example.class, Object.class, "s3", long.class); |
|
438 |
testFindStatic(Example.class, Object.class, "s4", int.class, int.class); |
|
439 |
testFindStatic(Example.class, Object.class, "s5", long.class, int.class); |
|
440 |
testFindStatic(Example.class, Object.class, "s6", int.class, long.class); |
|
441 |
testFindStatic(Example.class, Object.class, "s7", float.class, double.class); |
|
442 |
||
443 |
testFindStatic(false, PRIVATE, Example.class, void.class, "bogus"); |
|
444 |
} |
|
445 |
||
446 |
void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
447 |
for (Object[] ac : accessCases(defc, name)) { |
|
448 |
testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); |
|
449 |
} |
|
450 |
} |
|
451 |
void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
452 |
testFindStatic(true, lookup, defc, ret, name, params); |
|
453 |
} |
|
454 |
void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
455 |
countTest(positive); |
|
4537 | 456 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 457 |
MethodHandle target = null; |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
458 |
Exception noAccess = null; |
4535 | 459 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
460 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 461 |
target = lookup.findStatic(defc, name, type); |
462 |
} catch (NoAccessException ex) { |
|
463 |
noAccess = ex; |
|
464 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
465 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
466 |
System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target |
4535 | 467 |
+(noAccess == null ? "" : " !! "+noAccess)); |
468 |
if (positive && noAccess != null) throw noAccess; |
|
469 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
470 |
if (!positive) return; // negative test failed as expected |
|
471 |
assertEquals(type, target.type()); |
|
472 |
assertTrue(target.toString().contains(name)); // rough check |
|
473 |
if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
|
474 |
Object[] args = randomArgs(params); |
|
475 |
printCalled(target, name, args); |
|
4537 | 476 |
target.invokeVarargs(args); |
4535 | 477 |
assertCalled(name, args); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
478 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
479 |
System.out.print(':'); |
4535 | 480 |
} |
481 |
||
482 |
@Test |
|
483 |
public void testFindVirtual() throws Throwable { |
|
484 |
if (CAN_SKIP_WORKING) return; |
|
485 |
startTest("findVirtual"); |
|
486 |
testFindVirtual(Example.class, void.class, "v0"); |
|
487 |
testFindVirtual(Example.class, void.class, "pkg_v0"); |
|
488 |
testFindVirtual(Example.class, void.class, "pri_v0"); |
|
489 |
testFindVirtual(Example.class, Object.class, "v1", Object.class); |
|
490 |
testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class); |
|
491 |
testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class); |
|
492 |
testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class); |
|
493 |
testFindVirtual(Example.class, Object.class, "v2", int.class, int.class); |
|
494 |
testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus"); |
|
495 |
// test dispatch |
|
496 |
testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0"); |
|
497 |
testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0"); |
|
498 |
testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0"); |
|
499 |
testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0"); |
|
500 |
testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0"); |
|
501 |
testFindVirtual(Example.class, IntExample.class, void.class, "v0"); |
|
502 |
testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0"); |
|
503 |
} |
|
504 |
||
505 |
void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
506 |
Class<?> rcvc = defc; |
|
507 |
testFindVirtual(rcvc, defc, ret, name, params); |
|
508 |
} |
|
509 |
void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
510 |
for (Object[] ac : accessCases(defc, name)) { |
|
511 |
testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params); |
|
512 |
} |
|
513 |
} |
|
514 |
void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
515 |
testFindVirtual(true, lookup, rcvc, defc, ret, name, params); |
|
516 |
} |
|
517 |
void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
518 |
countTest(positive); |
|
519 |
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
|
4537 | 520 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 521 |
MethodHandle target = null; |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
522 |
Exception noAccess = null; |
4535 | 523 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
524 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 525 |
target = lookup.findVirtual(defc, methodName, type); |
526 |
} catch (NoAccessException ex) { |
|
527 |
noAccess = ex; |
|
528 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
529 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
530 |
System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target |
4535 | 531 |
+(noAccess == null ? "" : " !! "+noAccess)); |
532 |
if (positive && noAccess != null) throw noAccess; |
|
533 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
534 |
if (!positive) return; // negative test failed as expected |
|
535 |
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
|
4537 | 536 |
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
537 |
assertEquals(typeWithSelf, target.type()); |
4535 | 538 |
assertTrue(target.toString().contains(methodName)); // rough check |
539 |
if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
|
540 |
Object[] argsWithSelf = randomArgs(paramsWithSelf); |
|
541 |
if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
|
542 |
printCalled(target, name, argsWithSelf); |
|
4537 | 543 |
target.invokeVarargs(argsWithSelf); |
4535 | 544 |
assertCalled(name, argsWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
545 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
546 |
System.out.print(':'); |
4535 | 547 |
} |
548 |
||
549 |
@Test |
|
550 |
public void testFindSpecial() throws Throwable { |
|
551 |
if (CAN_SKIP_WORKING) return; |
|
552 |
startTest("findSpecial"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
553 |
testFindSpecial(SubExample.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
554 |
testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
555 |
// Do some negative testing: |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
556 |
for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
557 |
testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
558 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
559 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
560 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
561 |
} |
4535 | 562 |
} |
563 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
564 |
void testFindSpecial(Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
565 |
Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
566 |
testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
567 |
testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
568 |
testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
569 |
testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); |
4535 | 570 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
571 |
void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
572 |
Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4535 | 573 |
countTest(positive); |
4537 | 574 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 575 |
MethodHandle target = null; |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
576 |
Exception noAccess = null; |
4535 | 577 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
578 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
579 |
target = lookup.findSpecial(defc, name, type, specialCaller); |
4535 | 580 |
} catch (NoAccessException ex) { |
581 |
noAccess = ex; |
|
582 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
583 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
584 |
System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
585 |
+(target == null ? "" : target.type()) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
586 |
+(noAccess == null ? "" : " !! "+noAccess)); |
4535 | 587 |
if (positive && noAccess != null) throw noAccess; |
588 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
589 |
if (!positive) return; // negative test failed as expected |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
590 |
assertEquals(specialCaller, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
591 |
assertEquals(type, target.type().dropParameterTypes(0,1)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
592 |
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); |
4537 | 593 |
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
4535 | 594 |
assertTrue(target.toString().contains(name)); // rough check |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
595 |
if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return; |
4535 | 596 |
Object[] args = randomArgs(paramsWithSelf); |
597 |
printCalled(target, name, args); |
|
4537 | 598 |
target.invokeVarargs(args); |
4535 | 599 |
assertCalled(name, args); |
600 |
} |
|
601 |
||
602 |
@Test |
|
603 |
public void testBind() throws Throwable { |
|
604 |
if (CAN_SKIP_WORKING) return; |
|
605 |
startTest("bind"); |
|
606 |
testBind(Example.class, void.class, "v0"); |
|
607 |
testBind(Example.class, void.class, "pkg_v0"); |
|
608 |
testBind(Example.class, void.class, "pri_v0"); |
|
609 |
testBind(Example.class, Object.class, "v1", Object.class); |
|
610 |
testBind(Example.class, Object.class, "v2", Object.class, Object.class); |
|
611 |
testBind(Example.class, Object.class, "v2", Object.class, int.class); |
|
612 |
testBind(Example.class, Object.class, "v2", int.class, Object.class); |
|
613 |
testBind(Example.class, Object.class, "v2", int.class, int.class); |
|
614 |
testBind(false, PRIVATE, Example.class, void.class, "bogus"); |
|
615 |
testBind(SubExample.class, void.class, "Sub/v0"); |
|
616 |
testBind(SubExample.class, void.class, "Sub/pkg_v0"); |
|
617 |
testBind(IntExample.Impl.class, void.class, "Int/v0"); |
|
618 |
} |
|
619 |
||
620 |
void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
621 |
for (Object[] ac : accessCases(defc, name)) { |
|
622 |
testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); |
|
623 |
} |
|
624 |
} |
|
625 |
||
626 |
void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
627 |
countTest(positive); |
|
628 |
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
|
4537 | 629 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 630 |
Object receiver = randomArg(defc); |
631 |
MethodHandle target = null; |
|
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
632 |
Exception noAccess = null; |
4535 | 633 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
634 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 635 |
target = lookup.bind(receiver, methodName, type); |
636 |
} catch (NoAccessException ex) { |
|
637 |
noAccess = ex; |
|
638 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
639 |
if (verbosity >= 3) |
4535 | 640 |
System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target |
641 |
+(noAccess == null ? "" : " !! "+noAccess)); |
|
642 |
if (positive && noAccess != null) throw noAccess; |
|
643 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
644 |
if (!positive) return; // negative test failed as expected |
|
645 |
assertEquals(type, target.type()); |
|
646 |
Object[] args = randomArgs(params); |
|
647 |
printCalled(target, name, args); |
|
4537 | 648 |
target.invokeVarargs(args); |
4535 | 649 |
Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); |
650 |
assertCalled(name, argsWithReceiver); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
651 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
652 |
System.out.print(':'); |
4535 | 653 |
} |
654 |
||
655 |
@Test |
|
656 |
public void testUnreflect() throws Throwable { |
|
657 |
if (CAN_SKIP_WORKING) return; |
|
658 |
startTest("unreflect"); |
|
659 |
testUnreflect(Example.class, true, void.class, "s0"); |
|
660 |
testUnreflect(Example.class, true, void.class, "pkg_s0"); |
|
661 |
testUnreflect(Example.class, true, void.class, "pri_s0"); |
|
662 |
||
663 |
testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
|
664 |
testUnreflect(Example.class, true, Object.class, "s2", int.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
665 |
testUnreflect(Example.class, true, Object.class, "s3", long.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
666 |
testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
667 |
testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
668 |
testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
4535 | 669 |
|
670 |
testUnreflect(Example.class, false, void.class, "v0"); |
|
671 |
testUnreflect(Example.class, false, void.class, "pkg_v0"); |
|
672 |
testUnreflect(Example.class, false, void.class, "pri_v0"); |
|
673 |
testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
|
674 |
testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class); |
|
675 |
testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class); |
|
676 |
testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class); |
|
677 |
testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
|
678 |
} |
|
679 |
||
680 |
void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
681 |
for (Object[] ac : accessCases(defc, name)) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
682 |
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); |
4535 | 683 |
} |
684 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
685 |
void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
686 |
for (Object[] ac : accessCases(defc, name)) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
687 |
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
688 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
689 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
690 |
void testUnreflectMaybeSpecial(Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
691 |
boolean positive, Lookup lookup, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
692 |
Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4535 | 693 |
countTest(positive); |
4537 | 694 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 695 |
Method rmethod = null; |
696 |
MethodHandle target = null; |
|
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
697 |
Exception noAccess = null; |
4535 | 698 |
try { |
699 |
rmethod = defc.getDeclaredMethod(name, params); |
|
700 |
} catch (NoSuchMethodException ex) { |
|
701 |
throw new NoAccessException(ex); |
|
702 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
703 |
boolean isStatic = (rcvc == null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
704 |
boolean isSpecial = (specialCaller != null); |
4535 | 705 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
706 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
707 |
if (isSpecial) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
708 |
target = lookup.unreflectSpecial(rmethod, specialCaller); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
709 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
710 |
target = lookup.unreflect(rmethod); |
4535 | 711 |
} catch (NoAccessException ex) { |
712 |
noAccess = ex; |
|
713 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
714 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
715 |
System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
716 |
+(!isSpecial ? "" : " specialCaller="+specialCaller) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
717 |
+( isStatic ? "" : " receiver="+rcvc) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
718 |
+" => "+target |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
719 |
+(noAccess == null ? "" : " !! "+noAccess)); |
4535 | 720 |
if (positive && noAccess != null) throw noAccess; |
721 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
722 |
if (!positive) return; // negative test failed as expected |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
723 |
assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
4535 | 724 |
Class<?>[] paramsMaybeWithSelf = params; |
725 |
if (!isStatic) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
726 |
paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); |
4535 | 727 |
} |
4537 | 728 |
MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
729 |
if (isStatic) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
730 |
assertEquals(typeMaybeWithSelf, target.type()); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
731 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
732 |
if (isSpecial) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
733 |
assertEquals(specialCaller, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
734 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
735 |
assertEquals(defc, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
736 |
assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
737 |
} |
4535 | 738 |
Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
739 |
printCalled(target, name, argsMaybeWithSelf); |
|
4537 | 740 |
target.invokeVarargs(argsMaybeWithSelf); |
4535 | 741 |
assertCalled(name, argsMaybeWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
742 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
743 |
System.out.print(':'); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
744 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
745 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
746 |
void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
747 |
for (Object[] ac : accessCases(defc, name, true)) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
748 |
Class<?> specialCaller = rcvc; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
749 |
testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
750 |
} |
4535 | 751 |
} |
752 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
753 |
@Test |
4535 | 754 |
public void testUnreflectSpecial() throws Throwable { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
755 |
if (CAN_SKIP_WORKING) return; |
4535 | 756 |
startTest("unreflectSpecial"); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
757 |
testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
758 |
testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
759 |
testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
760 |
testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
761 |
testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
762 |
testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
763 |
testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); |
4535 | 764 |
} |
765 |
||
4537 | 766 |
public static class HasFields { |
767 |
boolean fZ = false; |
|
768 |
byte fB = (byte)'B'; |
|
769 |
short fS = (short)'S'; |
|
770 |
char fC = 'C'; |
|
771 |
int fI = 'I'; |
|
772 |
long fJ = 'J'; |
|
773 |
float fF = 'F'; |
|
774 |
double fD = 'D'; |
|
775 |
static boolean sZ = true; |
|
776 |
static byte sB = 1+(byte)'B'; |
|
777 |
static short sS = 1+(short)'S'; |
|
778 |
static char sC = 1+'C'; |
|
779 |
static int sI = 1+'I'; |
|
780 |
static long sJ = 1+'J'; |
|
781 |
static float sF = 1+'F'; |
|
782 |
static double sD = 1+'D'; |
|
783 |
||
784 |
Object fL = 'L'; |
|
785 |
String fR = "R"; |
|
786 |
static Object sL = 'M'; |
|
787 |
static String sR = "S"; |
|
788 |
||
789 |
static final Object[][] CASES; |
|
790 |
static { |
|
791 |
ArrayList<Object[]> cases = new ArrayList<Object[]>(); |
|
792 |
Object types[][] = { |
|
793 |
{'L',Object.class}, {'R',String.class}, |
|
794 |
{'I',int.class}, {'J',long.class}, |
|
795 |
{'F',float.class}, {'D',double.class}, |
|
796 |
{'Z',boolean.class}, {'B',byte.class}, |
|
797 |
{'S',short.class}, {'C',char.class}, |
|
798 |
}; |
|
799 |
HasFields fields = new HasFields(); |
|
800 |
for (Object[] t : types) { |
|
801 |
for (int kind = 0; kind <= 1; kind++) { |
|
802 |
boolean isStatic = (kind != 0); |
|
803 |
char btc = (Character)t[0]; |
|
804 |
String name = (isStatic ? "s" : "f") + btc; |
|
805 |
Class<?> type = (Class<?>) t[1]; |
|
806 |
Object value; |
|
807 |
Field field; |
|
808 |
try { |
|
809 |
field = HasFields.class.getDeclaredField(name); |
|
810 |
} catch (Exception ex) { |
|
811 |
throw new InternalError("no field HasFields."+name); |
|
812 |
} |
|
813 |
try { |
|
814 |
value = field.get(fields); |
|
815 |
} catch (Exception ex) { |
|
816 |
throw new InternalError("cannot fetch field HasFields."+name); |
|
817 |
} |
|
818 |
if (type == float.class) { |
|
819 |
float v = 'F'; |
|
820 |
if (isStatic) v++; |
|
821 |
assert(value.equals(v)); |
|
822 |
} |
|
823 |
assert(name.equals(field.getName())); |
|
824 |
assert(type.equals(field.getType())); |
|
825 |
assert(isStatic == (Modifier.isStatic(field.getModifiers()))); |
|
826 |
cases.add(new Object[]{ field, value }); |
|
827 |
} |
|
828 |
} |
|
829 |
CASES = cases.toArray(new Object[0][]); |
|
830 |
} |
|
831 |
} |
|
832 |
||
5726 | 833 |
static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC_FIELD = 3; |
834 |
static boolean testModeMatches(int testMode, boolean isStatic) { |
|
835 |
switch (testMode) { |
|
836 |
case TEST_FIND_STATIC_FIELD: return isStatic; |
|
837 |
case TEST_FIND_FIELD: return !isStatic; |
|
838 |
default: return true; // unreflect matches both |
|
839 |
} |
|
840 |
} |
|
841 |
||
4537 | 842 |
@Test |
4535 | 843 |
public void testUnreflectGetter() throws Throwable { |
5726 | 844 |
startTest("unreflectGetter"); |
845 |
testGetter(TEST_UNREFLECT); |
|
846 |
} |
|
847 |
@Test |
|
848 |
public void testFindGetter() throws Throwable { |
|
849 |
startTest("findGetter"); |
|
850 |
testGetter(TEST_FIND_FIELD); |
|
851 |
} |
|
852 |
@Test |
|
853 |
public void testFindStaticGetter() throws Throwable { |
|
854 |
startTest("findStaticGetter"); |
|
855 |
testGetter(TEST_FIND_STATIC_FIELD); |
|
856 |
} |
|
857 |
public void testGetter(int testMode) throws Throwable { |
|
4535 | 858 |
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
4537 | 859 |
for (Object[] c : HasFields.CASES) { |
860 |
Field f = (Field)c[0]; |
|
861 |
Object value = c[1]; |
|
862 |
Class<?> type = f.getType(); |
|
5726 | 863 |
testGetter(lookup, f, type, value, testMode); |
4537 | 864 |
} |
865 |
} |
|
5726 | 866 |
public void testGetter(MethodHandles.Lookup lookup, |
867 |
Field f, Class<?> type, Object value, int testMode) throws Throwable { |
|
868 |
boolean isStatic = Modifier.isStatic(f.getModifiers()); |
|
869 |
Class<?> fclass = f.getDeclaringClass(); |
|
870 |
String fname = f.getName(); |
|
871 |
Class<?> ftype = f.getType(); |
|
872 |
if (!testModeMatches(testMode, isStatic)) return; |
|
4537 | 873 |
countTest(true); |
874 |
MethodType expType = MethodType.methodType(type, HasFields.class); |
|
875 |
if (isStatic) expType = expType.dropParameterTypes(0, 1); |
|
876 |
MethodHandle mh = lookup.unreflectGetter(f); |
|
877 |
assertSame(mh.type(), expType); |
|
5726 | 878 |
assertEquals(mh.toString(), fname); |
4537 | 879 |
HasFields fields = new HasFields(); |
880 |
Object sawValue; |
|
881 |
Class<?> rtype = type; |
|
882 |
if (type != int.class) rtype = Object.class; |
|
883 |
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype)); |
|
884 |
Object expValue = value; |
|
885 |
for (int i = 0; i <= 1; i++) { |
|
886 |
if (isStatic) { |
|
887 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
888 |
sawValue = mh.<int>invokeExact(); // do these exactly |
4537 | 889 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
890 |
sawValue = mh.invokeExact(); |
4537 | 891 |
} else { |
892 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
893 |
sawValue = mh.<int>invokeExact((Object) fields); |
4537 | 894 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
895 |
sawValue = mh.invokeExact((Object) fields); |
4537 | 896 |
} |
897 |
assertEquals(sawValue, expValue); |
|
898 |
Object random = randomArg(type); |
|
899 |
f.set(fields, random); |
|
900 |
expValue = random; |
|
901 |
} |
|
902 |
f.set(fields, value); // put it back |
|
4535 | 903 |
} |
904 |
||
4537 | 905 |
|
906 |
@Test |
|
4535 | 907 |
public void testUnreflectSetter() throws Throwable { |
5726 | 908 |
startTest("unreflectSetter"); |
909 |
testSetter(TEST_UNREFLECT); |
|
910 |
} |
|
911 |
@Test |
|
912 |
public void testFindSetter() throws Throwable { |
|
913 |
startTest("findSetter"); |
|
914 |
testSetter(TEST_FIND_FIELD); |
|
915 |
} |
|
916 |
@Test |
|
917 |
public void testFindStaticSetter() throws Throwable { |
|
918 |
startTest("findStaticSetter"); |
|
919 |
testSetter(TEST_FIND_STATIC_FIELD); |
|
920 |
} |
|
921 |
public void testSetter(int testMode) throws Throwable { |
|
4535 | 922 |
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
923 |
startTest("unreflectSetter"); |
|
4537 | 924 |
for (Object[] c : HasFields.CASES) { |
925 |
Field f = (Field)c[0]; |
|
926 |
Object value = c[1]; |
|
927 |
Class<?> type = f.getType(); |
|
5726 | 928 |
testSetter(lookup, f, type, value, testMode); |
4537 | 929 |
} |
930 |
} |
|
5726 | 931 |
public void testSetter(MethodHandles.Lookup lookup, |
932 |
Field f, Class<?> type, Object value, int testMode) throws Throwable { |
|
933 |
boolean isStatic = Modifier.isStatic(f.getModifiers()); |
|
934 |
Class<?> fclass = f.getDeclaringClass(); |
|
935 |
String fname = f.getName(); |
|
936 |
Class<?> ftype = f.getType(); |
|
937 |
if (!testModeMatches(testMode, isStatic)) return; |
|
4537 | 938 |
countTest(true); |
939 |
MethodType expType = MethodType.methodType(void.class, HasFields.class, type); |
|
940 |
if (isStatic) expType = expType.dropParameterTypes(0, 1); |
|
5726 | 941 |
MethodHandle mh; |
942 |
if (testMode == TEST_UNREFLECT) |
|
943 |
mh = lookup.unreflectSetter(f); |
|
944 |
else if (testMode == TEST_FIND_FIELD) |
|
945 |
mh = lookup.findSetter(fclass, fname, ftype); |
|
946 |
else if (testMode == TEST_FIND_STATIC_FIELD) |
|
947 |
mh = lookup.findStaticSetter(fclass, fname, ftype); |
|
948 |
else throw new InternalError(); |
|
4537 | 949 |
assertSame(mh.type(), expType); |
5726 | 950 |
assertEquals(mh.toString(), fname); |
4537 | 951 |
HasFields fields = new HasFields(); |
952 |
Object sawValue; |
|
953 |
Class<?> vtype = type; |
|
954 |
if (type != int.class) vtype = Object.class; |
|
955 |
int last = mh.type().parameterCount() - 1; |
|
956 |
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype)); |
|
957 |
assertEquals(f.get(fields), value); // clean to start with |
|
958 |
for (int i = 0; i <= 1; i++) { |
|
959 |
Object putValue = randomArg(type); |
|
960 |
if (isStatic) { |
|
961 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
962 |
mh.<void>invokeExact((int)(Integer)putValue); // do these exactly |
4537 | 963 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
964 |
mh.<void>invokeExact(putValue); |
4537 | 965 |
} else { |
966 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
967 |
mh.<void>invokeExact((Object) fields, (int)(Integer)putValue); |
4537 | 968 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
969 |
mh.<void>invokeExact((Object) fields, putValue); |
4537 | 970 |
} |
971 |
assertEquals(f.get(fields), putValue); |
|
972 |
} |
|
973 |
f.set(fields, value); // put it back |
|
4535 | 974 |
} |
975 |
||
4537 | 976 |
@Test |
4535 | 977 |
public void testArrayElementGetter() throws Throwable { |
978 |
startTest("arrayElementGetter"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
979 |
testArrayElementGetterSetter(false); |
4537 | 980 |
} |
981 |
||
982 |
@Test |
|
983 |
public void testArrayElementSetter() throws Throwable { |
|
984 |
startTest("arrayElementSetter"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
985 |
testArrayElementGetterSetter(true); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
986 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
987 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
988 |
public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
989 |
testArrayElementGetterSetter(new Object[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
990 |
testArrayElementGetterSetter(new String[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
991 |
testArrayElementGetterSetter(new boolean[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
992 |
testArrayElementGetterSetter(new byte[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
993 |
testArrayElementGetterSetter(new char[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
994 |
testArrayElementGetterSetter(new short[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
995 |
testArrayElementGetterSetter(new int[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
996 |
testArrayElementGetterSetter(new float[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
997 |
testArrayElementGetterSetter(new long[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
998 |
testArrayElementGetterSetter(new double[10], testSetter); |
4535 | 999 |
} |
1000 |
||
4537 | 1001 |
public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
1002 |
countTest(true); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1003 |
if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]"); |
4537 | 1004 |
Class<?> arrayType = array.getClass(); |
1005 |
Class<?> elemType = arrayType.getComponentType(); |
|
1006 |
MethodType expType = !testSetter |
|
1007 |
? MethodType.methodType(elemType, arrayType, int.class) |
|
1008 |
: MethodType.methodType(void.class, arrayType, int.class, elemType); |
|
1009 |
MethodHandle mh = !testSetter |
|
1010 |
? MethodHandles.arrayElementGetter(arrayType) |
|
1011 |
: MethodHandles.arrayElementSetter(arrayType); |
|
1012 |
assertSame(mh.type(), expType); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1013 |
if (elemType != int.class && elemType != boolean.class) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1014 |
MethodType gtype; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1015 |
if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1016 |
gtype = mh.type().changeParameterType(0, Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1017 |
if (testSetter) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1018 |
gtype = gtype.changeParameterType(2, Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1019 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1020 |
gtype = gtype.changeReturnType(Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1021 |
} else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1022 |
// FIXME: This simpler path hits a bug in convertArguments => ToGeneric |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1023 |
gtype = mh.type().generic().changeParameterType(1, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1024 |
mh = MethodHandles.convertArguments(mh, gtype); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1025 |
} |
4537 | 1026 |
Object sawValue, expValue; |
1027 |
List<Object> model = array2list(array); |
|
1028 |
int length = Array.getLength(array); |
|
1029 |
for (int i = 0; i < length; i++) { |
|
1030 |
// update array element |
|
1031 |
Object random = randomArg(elemType); |
|
1032 |
model.set(i, random); |
|
1033 |
if (testSetter) { |
|
1034 |
if (elemType == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1035 |
mh.<void>invokeExact((int[]) array, i, (int)(Integer)random); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1036 |
else if (elemType == boolean.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1037 |
mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random); |
4537 | 1038 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1039 |
mh.<void>invokeExact(array, i, random); |
4537 | 1040 |
assertEquals(model, array2list(array)); |
1041 |
} else { |
|
1042 |
Array.set(array, i, random); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1043 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1044 |
if (verbosity >= 5) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1045 |
List<Object> array2list = array2list(array); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1046 |
System.out.println("a["+i+"]="+random+" => "+array2list); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1047 |
if (!array2list.equals(model)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1048 |
System.out.println("*** != "+model); |
4537 | 1049 |
} |
1050 |
// observe array element |
|
1051 |
sawValue = Array.get(array, i); |
|
1052 |
if (!testSetter) { |
|
1053 |
expValue = sawValue; |
|
1054 |
if (elemType == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1055 |
sawValue = mh.<int>invokeExact((int[]) array, i); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1056 |
else if (elemType == boolean.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1057 |
sawValue = mh.<boolean>invokeExact((boolean[]) array, i); |
4537 | 1058 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1059 |
sawValue = mh.invokeExact(array, i); |
4537 | 1060 |
assertEquals(sawValue, expValue); |
1061 |
assertEquals(model, array2list(array)); |
|
1062 |
} |
|
1063 |
} |
|
1064 |
} |
|
1065 |
||
1066 |
List<Object> array2list(Object array) { |
|
1067 |
int length = Array.getLength(array); |
|
1068 |
ArrayList<Object> model = new ArrayList<Object>(length); |
|
1069 |
for (int i = 0; i < length; i++) |
|
1070 |
model.add(Array.get(array, i)); |
|
1071 |
return model; |
|
4535 | 1072 |
} |
1073 |
||
1074 |
static class Callee { |
|
1075 |
static Object id() { return called("id"); } |
|
1076 |
static Object id(Object x) { return called("id", x); } |
|
1077 |
static Object id(Object x, Object y) { return called("id", x, y); } |
|
1078 |
static Object id(Object x, Object y, Object z) { return called("id", x, y, z); } |
|
1079 |
static Object id(Object... vx) { return called("id", vx); } |
|
1080 |
static MethodHandle ofType(int n) { |
|
1081 |
return ofType(Object.class, n); |
|
1082 |
} |
|
1083 |
static MethodHandle ofType(Class<?> rtype, int n) { |
|
1084 |
if (n == -1) |
|
4537 | 1085 |
return ofType(MethodType.methodType(rtype, Object[].class)); |
1086 |
return ofType(MethodType.genericMethodType(n).changeReturnType(rtype)); |
|
4535 | 1087 |
} |
1088 |
static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) { |
|
4537 | 1089 |
return ofType(MethodType.methodType(rtype, ptypes)); |
4535 | 1090 |
} |
1091 |
static MethodHandle ofType(MethodType type) { |
|
1092 |
Class<?> rtype = type.returnType(); |
|
1093 |
String pfx = ""; |
|
1094 |
if (rtype != Object.class) |
|
1095 |
pfx = rtype.getSimpleName().substring(0, 1).toLowerCase(); |
|
1096 |
String name = pfx+"id"; |
|
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1097 |
try { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1098 |
return PRIVATE.findStatic(Callee.class, name, type); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1099 |
} catch (Exception ex) { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1100 |
throw new RuntimeException(ex); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1101 |
} |
4535 | 1102 |
} |
1103 |
} |
|
1104 |
||
1105 |
@Test |
|
1106 |
public void testConvertArguments() throws Throwable { |
|
1107 |
if (CAN_SKIP_WORKING) return; |
|
1108 |
startTest("convertArguments"); |
|
1109 |
testConvert(Callee.ofType(1), null, "id", int.class); |
|
1110 |
testConvert(Callee.ofType(1), null, "id", String.class); |
|
1111 |
testConvert(Callee.ofType(1), null, "id", Integer.class); |
|
1112 |
testConvert(Callee.ofType(1), null, "id", short.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1113 |
testConvert(Callee.ofType(1), null, "id", char.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1114 |
testConvert(Callee.ofType(1), null, "id", byte.class); |
4535 | 1115 |
} |
1116 |
||
1117 |
void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable { |
|
1118 |
testConvert(true, id, rtype, name, params); |
|
1119 |
} |
|
1120 |
||
1121 |
void testConvert(boolean positive, MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable { |
|
1122 |
countTest(positive); |
|
1123 |
MethodType idType = id.type(); |
|
1124 |
if (rtype == null) rtype = idType.returnType(); |
|
1125 |
for (int i = 0; i < params.length; i++) { |
|
1126 |
if (params[i] == null) params[i] = idType.parameterType(i); |
|
1127 |
} |
|
1128 |
// simulate the pairwise conversion |
|
4537 | 1129 |
MethodType newType = MethodType.methodType(rtype, params); |
4535 | 1130 |
Object[] args = randomArgs(newType.parameterArray()); |
1131 |
Object[] convArgs = args.clone(); |
|
1132 |
for (int i = 0; i < args.length; i++) { |
|
1133 |
Class<?> src = newType.parameterType(i); |
|
1134 |
Class<?> dst = idType.parameterType(i); |
|
1135 |
if (src != dst) |
|
1136 |
convArgs[i] = castToWrapper(convArgs[i], dst); |
|
1137 |
} |
|
4537 | 1138 |
Object convResult = id.invokeVarargs(convArgs); |
4535 | 1139 |
{ |
1140 |
Class<?> dst = newType.returnType(); |
|
1141 |
Class<?> src = idType.returnType(); |
|
1142 |
if (src != dst) |
|
1143 |
convResult = castToWrapper(convResult, dst); |
|
1144 |
} |
|
1145 |
MethodHandle target = null; |
|
1146 |
RuntimeException error = null; |
|
1147 |
try { |
|
1148 |
target = MethodHandles.convertArguments(id, newType); |
|
1149 |
} catch (RuntimeException ex) { |
|
1150 |
error = ex; |
|
1151 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1152 |
if (verbosity >= 3) |
4535 | 1153 |
System.out.println("convert "+id+ " to "+newType+" => "+target |
1154 |
+(error == null ? "" : " !! "+error)); |
|
1155 |
if (positive && error != null) throw error; |
|
1156 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
1157 |
if (!positive) return; // negative test failed as expected |
|
1158 |
assertEquals(newType, target.type()); |
|
1159 |
printCalled(target, id.toString(), args); |
|
4537 | 1160 |
Object result = target.invokeVarargs(args); |
4535 | 1161 |
assertCalled(name, convArgs); |
1162 |
assertEquals(convResult, result); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1163 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1164 |
System.out.print(':'); |
4535 | 1165 |
} |
1166 |
||
1167 |
@Test |
|
4537 | 1168 |
public void testPermuteArguments() throws Throwable { |
1169 |
if (CAN_SKIP_WORKING) return; |
|
1170 |
startTest("permuteArguments"); |
|
1171 |
testPermuteArguments(4, Integer.class, 2, String.class, 0); |
|
1172 |
//testPermuteArguments(6, Integer.class, 0, null, 30); |
|
1173 |
//testPermuteArguments(4, Integer.class, 1, int.class, 6); |
|
1174 |
} |
|
1175 |
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1176 |
if (verbosity >= 2) |
4537 | 1177 |
System.out.println("permuteArguments "+max+"*"+type1.getName() |
1178 |
+(t2c==0?"":"/"+t2c+"*"+type2.getName()) |
|
1179 |
+(dilution > 0 ? " with dilution "+dilution : "")); |
|
1180 |
int t2pos = t2c == 0 ? 0 : 1; |
|
1181 |
for (int inargs = t2pos+1; inargs <= max; inargs++) { |
|
1182 |
Class<?>[] types = new Class<?>[inargs]; |
|
1183 |
Arrays.fill(types, type1); |
|
1184 |
if (t2c != 0) { |
|
1185 |
// Fill in a middle range with type2: |
|
1186 |
Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2); |
|
1187 |
} |
|
1188 |
Object[] args = randomArgs(types); |
|
1189 |
int numcases = 1; |
|
1190 |
for (int outargs = 0; outargs <= max; outargs++) { |
|
1191 |
if (outargs - inargs >= MAX_ARG_INCREASE) continue; |
|
1192 |
int[] reorder = new int[outargs]; |
|
1193 |
int casStep = dilution + 1; |
|
1194 |
// Avoid some common factors: |
|
1195 |
while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) || |
|
1196 |
(casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0)) |
|
1197 |
casStep++; |
|
1198 |
for (int cas = 0; cas < numcases; cas += casStep) { |
|
1199 |
for (int i = 0, c = cas; i < outargs; i++) { |
|
1200 |
reorder[i] = c % inargs; |
|
1201 |
c /= inargs; |
|
1202 |
} |
|
1203 |
testPermuteArguments(args, types, reorder); |
|
1204 |
} |
|
1205 |
numcases *= inargs; |
|
1206 |
if (dilution > 10 && outargs >= 4) { |
|
1207 |
// Do some special patterns, which we probably missed. |
|
1208 |
// Replication of a single argument or argument pair. |
|
1209 |
for (int i = 0; i < inargs; i++) { |
|
1210 |
Arrays.fill(reorder, i); |
|
1211 |
testPermuteArguments(args, types, reorder); |
|
1212 |
for (int d = 1; d <= 2; d++) { |
|
1213 |
if (i + d >= inargs) continue; |
|
1214 |
for (int j = 1; j < outargs; j += 2) |
|
1215 |
reorder[j] += 1; |
|
1216 |
testPermuteArguments(args, types, reorder); |
|
1217 |
testPermuteArguments(args, types, reverse(reorder)); |
|
1218 |
} |
|
1219 |
} |
|
1220 |
// Repetition of a sequence of 3 or more arguments. |
|
1221 |
for (int i = 1; i < inargs; i++) { |
|
1222 |
for (int len = 3; len <= inargs; len++) { |
|
1223 |
for (int j = 0; j < outargs; j++) |
|
1224 |
reorder[j] = (i + (j % len)) % inargs; |
|
1225 |
testPermuteArguments(args, types, reorder); |
|
1226 |
testPermuteArguments(args, types, reverse(reorder)); |
|
1227 |
} |
|
1228 |
} |
|
1229 |
} |
|
1230 |
} |
|
1231 |
} |
|
1232 |
} |
|
1233 |
||
1234 |
static int[] reverse(int[] reorder) { |
|
1235 |
reorder = reorder.clone(); |
|
1236 |
for (int i = 0, imax = reorder.length / 2; i < imax; i++) { |
|
1237 |
int j = reorder.length - 1 - i; |
|
1238 |
int tem = reorder[i]; |
|
1239 |
reorder[i] = reorder[j]; |
|
1240 |
reorder[j] = tem; |
|
1241 |
} |
|
1242 |
return reorder; |
|
1243 |
} |
|
1244 |
||
1245 |
void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable { |
|
1246 |
countTest(); |
|
1247 |
if (args == null && types == null) { |
|
1248 |
int max = 0; |
|
1249 |
for (int j : reorder) { |
|
1250 |
if (max < j) max = j; |
|
1251 |
} |
|
1252 |
args = randomArgs(max+1, Integer.class); |
|
1253 |
} |
|
1254 |
if (args == null) { |
|
1255 |
args = randomArgs(types); |
|
1256 |
} |
|
1257 |
if (types == null) { |
|
1258 |
types = new Class<?>[args.length]; |
|
1259 |
for (int i = 0; i < args.length; i++) |
|
1260 |
types[i] = args[i].getClass(); |
|
1261 |
} |
|
1262 |
int inargs = args.length, outargs = reorder.length; |
|
1263 |
assert(inargs == types.length); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1264 |
if (verbosity >= 3) |
4537 | 1265 |
System.out.println("permuteArguments "+Arrays.toString(reorder)); |
1266 |
Object[] permArgs = new Object[outargs]; |
|
1267 |
Class<?>[] permTypes = new Class<?>[outargs]; |
|
1268 |
for (int i = 0; i < outargs; i++) { |
|
1269 |
permArgs[i] = args[reorder[i]]; |
|
1270 |
permTypes[i] = types[reorder[i]]; |
|
1271 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1272 |
if (verbosity >= 4) { |
4537 | 1273 |
System.out.println("in args: "+Arrays.asList(args)); |
1274 |
System.out.println("out args: "+Arrays.asList(permArgs)); |
|
1275 |
System.out.println("in types: "+Arrays.asList(types)); |
|
1276 |
System.out.println("out types: "+Arrays.asList(permTypes)); |
|
1277 |
} |
|
1278 |
MethodType inType = MethodType.methodType(Object.class, types); |
|
1279 |
MethodType outType = MethodType.methodType(Object.class, permTypes); |
|
1280 |
MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType); |
|
1281 |
MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); |
|
1282 |
Object result = newTarget.invokeVarargs(args); |
|
1283 |
Object expected = Arrays.asList(permArgs); |
|
1284 |
assertEquals(expected, result); |
|
1285 |
} |
|
1286 |
||
1287 |
||
1288 |
@Test |
|
1289 |
public void testSpreadArguments() throws Throwable { |
|
1290 |
if (CAN_SKIP_WORKING) return; |
|
1291 |
startTest("spreadArguments"); |
|
1292 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1293 |
if (verbosity >= 3) |
4537 | 1294 |
System.out.println("spreadArguments "+argType); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1295 |
// FIXME: enable _adapter_spread_args and fix Fail_2 |
4537 | 1296 |
for (int nargs = 0; nargs < 10; nargs++) { |
1297 |
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
|
1298 |
for (int pos = 0; pos < nargs; pos++) { |
|
1299 |
if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1300 |
testSpreadArguments(argType, pos, nargs); |
4537 | 1301 |
} |
1302 |
} |
|
1303 |
} |
|
1304 |
} |
|
1305 |
public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
|
1306 |
countTest(); |
|
1307 |
MethodHandle target = ValueConversions.varargsArray(nargs); |
|
1308 |
MethodHandle target2 = changeArgTypes(target, argType); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1309 |
if (verbosity >= 3) |
4537 | 1310 |
System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1311 |
Object[] args = randomArgs(target2.type().parameterArray()); |
|
1312 |
// make sure the target does what we think it does: |
|
1313 |
if (pos == 0 && nargs < 5) { |
|
1314 |
Object[] check = (Object[]) target.invokeVarargs(args); |
|
1315 |
assertArrayEquals(args, check); |
|
1316 |
switch (nargs) { |
|
1317 |
case 0: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1318 |
check = target.<Object[]>invokeExact(); |
4537 | 1319 |
assertArrayEquals(args, check); |
1320 |
break; |
|
1321 |
case 1: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1322 |
check = target.<Object[]>invokeExact(args[0]); |
4537 | 1323 |
assertArrayEquals(args, check); |
1324 |
break; |
|
1325 |
case 2: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1326 |
check = target.<Object[]>invokeExact(args[0], args[1]); |
4537 | 1327 |
assertArrayEquals(args, check); |
1328 |
break; |
|
1329 |
} |
|
1330 |
} |
|
1331 |
List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
|
1332 |
{ // modify newParams in place |
|
1333 |
List<Class<?>> spreadParams = newParams.subList(pos, nargs); |
|
1334 |
spreadParams.clear(); spreadParams.add(Object[].class); |
|
1335 |
} |
|
1336 |
MethodType newType = MethodType.methodType(Object.class, newParams); |
|
1337 |
MethodHandle result = MethodHandles.spreadArguments(target2, newType); |
|
1338 |
Object[] returnValue; |
|
1339 |
if (pos == 0) { |
|
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5727
diff
changeset
|
1340 |
Object rawRetVal = result.invokeExact(args); |
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5727
diff
changeset
|
1341 |
returnValue = (Object[]) rawRetVal; |
4537 | 1342 |
} else { |
1343 |
Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); |
|
1344 |
args1[pos] = Arrays.copyOfRange(args, pos, args.length); |
|
1345 |
returnValue = (Object[]) result.invokeVarargs(args1); |
|
1346 |
} |
|
1347 |
assertArrayEquals(args, returnValue); |
|
1348 |
} |
|
1349 |
||
1350 |
@Test |
|
1351 |
public void testCollectArguments() throws Throwable { |
|
1352 |
if (CAN_SKIP_WORKING) return; |
|
1353 |
startTest("collectArguments"); |
|
1354 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1355 |
if (verbosity >= 3) |
4537 | 1356 |
System.out.println("collectArguments "+argType); |
1357 |
for (int nargs = 0; nargs < 10; nargs++) { |
|
1358 |
for (int pos = 0; pos < nargs; pos++) { |
|
1359 |
if (argType == int.class) continue; // FIXME Fail_4 |
|
1360 |
testCollectArguments(argType, pos, nargs); |
|
1361 |
} |
|
1362 |
} |
|
1363 |
} |
|
1364 |
} |
|
1365 |
public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
|
1366 |
countTest(); |
|
1367 |
// fake up a MH with the same type as the desired adapter: |
|
1368 |
MethodHandle fake = ValueConversions.varargsArray(nargs); |
|
1369 |
fake = changeArgTypes(fake, argType); |
|
1370 |
MethodType newType = fake.type(); |
|
1371 |
Object[] args = randomArgs(newType.parameterArray()); |
|
1372 |
// here is what should happen: |
|
1373 |
Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); |
|
1374 |
collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); |
|
1375 |
// here is the MH which will witness the collected argument tail: |
|
1376 |
MethodHandle target = ValueConversions.varargsArray(pos+1); |
|
1377 |
target = changeArgTypes(target, 0, pos, argType); |
|
1378 |
target = changeArgTypes(target, pos, pos+1, Object[].class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1379 |
if (verbosity >= 3) |
4537 | 1380 |
System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); |
1381 |
MethodHandle result = MethodHandles.collectArguments(target, newType); |
|
1382 |
Object[] returnValue = (Object[]) result.invokeVarargs(args); |
|
1383 |
// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]); |
|
1384 |
// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]); |
|
1385 |
// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]); |
|
1386 |
assertArrayEquals(collectedArgs, returnValue); |
|
1387 |
} |
|
1388 |
||
1389 |
@Test |
|
4535 | 1390 |
public void testInsertArguments() throws Throwable { |
1391 |
if (CAN_SKIP_WORKING) return; |
|
1392 |
startTest("insertArguments"); |
|
1393 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1394 |
for (int ins = 0; ins <= 4; ins++) { |
|
1395 |
if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6 |
|
1396 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1397 |
testInsertArguments(nargs, pos, ins); |
|
1398 |
} |
|
1399 |
} |
|
1400 |
} |
|
1401 |
} |
|
1402 |
||
1403 |
void testInsertArguments(int nargs, int pos, int ins) throws Throwable { |
|
1404 |
countTest(); |
|
1405 |
MethodHandle target = ValueConversions.varargsArray(nargs + ins); |
|
1406 |
Object[] args = randomArgs(target.type().parameterArray()); |
|
1407 |
List<Object> resList = Arrays.asList(args); |
|
1408 |
List<Object> argsToPass = new ArrayList<Object>(resList); |
|
1409 |
List<Object> argsToInsert = argsToPass.subList(pos, pos + ins); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1410 |
if (verbosity >= 3) |
4535 | 1411 |
System.out.println("insert: "+argsToInsert+" into "+target); |
4537 | 1412 |
MethodHandle target2 = MethodHandles.insertArguments(target, pos, |
1413 |
(Object[]) argsToInsert.toArray()); |
|
4535 | 1414 |
argsToInsert.clear(); // remove from argsToInsert |
4537 | 1415 |
Object res2 = target2.invokeVarargs(argsToPass); |
4535 | 1416 |
Object res2List = Arrays.asList((Object[])res2); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1417 |
if (verbosity >= 3) |
4535 | 1418 |
System.out.println("result: "+res2List); |
1419 |
//if (!resList.equals(res2List)) |
|
1420 |
// System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List); |
|
1421 |
assertEquals(resList, res2List); |
|
1422 |
} |
|
1423 |
||
4537 | 1424 |
@Test |
1425 |
public void testFilterArguments() throws Throwable { |
|
1426 |
if (CAN_SKIP_WORKING) return; |
|
1427 |
startTest("filterArguments"); |
|
1428 |
for (int nargs = 1; nargs <= 6; nargs++) { |
|
1429 |
for (int pos = 0; pos < nargs; pos++) { |
|
1430 |
testFilterArguments(nargs, pos); |
|
1431 |
} |
|
1432 |
} |
|
1433 |
} |
|
1434 |
||
1435 |
void testFilterArguments(int nargs, int pos) throws Throwable { |
|
1436 |
countTest(); |
|
1437 |
MethodHandle target = ValueConversions.varargsList(nargs); |
|
1438 |
MethodHandle filter = ValueConversions.varargsList(1); |
|
1439 |
filter = MethodHandles.convertArguments(filter, filter.type().generic()); |
|
1440 |
Object[] argsToPass = randomArgs(nargs, Object.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1441 |
if (verbosity >= 3) |
4537 | 1442 |
System.out.println("filter "+target+" at "+pos+" with "+filter); |
1443 |
MethodHandle[] filters = new MethodHandle[pos*2+1]; |
|
1444 |
filters[pos] = filter; |
|
1445 |
MethodHandle target2 = MethodHandles.filterArguments(target, filters); |
|
1446 |
// Simulate expected effect of filter on arglist: |
|
1447 |
Object[] filteredArgs = argsToPass.clone(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1448 |
filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]); |
4537 | 1449 |
List<Object> expected = Arrays.asList(filteredArgs); |
1450 |
Object result = target2.invokeVarargs(argsToPass); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1451 |
if (verbosity >= 3) |
4537 | 1452 |
System.out.println("result: "+result); |
1453 |
if (!expected.equals(result)) |
|
1454 |
System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result); |
|
1455 |
assertEquals(expected, result); |
|
1456 |
} |
|
1457 |
||
1458 |
@Test |
|
1459 |
public void testFoldArguments() throws Throwable { |
|
1460 |
if (CAN_SKIP_WORKING) return; |
|
1461 |
startTest("foldArguments"); |
|
1462 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1463 |
for (int fold = 0; fold <= nargs; fold++) { |
|
1464 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1465 |
testFoldArguments(nargs, pos, fold); |
|
1466 |
} |
|
1467 |
} |
|
1468 |
} |
|
1469 |
} |
|
1470 |
||
1471 |
void testFoldArguments(int nargs, int pos, int fold) throws Throwable { |
|
1472 |
if (pos != 0) return; // can fold only at pos=0 for now |
|
1473 |
countTest(); |
|
1474 |
MethodHandle target = ValueConversions.varargsList(1 + nargs); |
|
7554
8a0ad9757002
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
7053
diff
changeset
|
1475 |
MethodHandle combine = ValueConversions.varargsList(fold).asType(MethodType.genericMethodType(fold)); |
4537 | 1476 |
List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1477 |
if (verbosity >= 3) |
4537 | 1478 |
System.out.println("fold "+target+" with "+combine); |
1479 |
MethodHandle target2 = MethodHandles.foldArguments(target, combine); |
|
1480 |
// Simulate expected effect of combiner on arglist: |
|
1481 |
List<Object> expected = new ArrayList<Object>(argsToPass); |
|
1482 |
List<Object> argsToFold = expected.subList(pos, pos + fold); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1483 |
if (verbosity >= 3) |
4537 | 1484 |
System.out.println("fold: "+argsToFold+" into "+target2); |
1485 |
Object foldedArgs = combine.invokeVarargs(argsToFold); |
|
1486 |
argsToFold.add(0, foldedArgs); |
|
1487 |
Object result = target2.invokeVarargs(argsToPass); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1488 |
if (verbosity >= 3) |
4537 | 1489 |
System.out.println("result: "+result); |
1490 |
if (!expected.equals(result)) |
|
1491 |
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result); |
|
1492 |
assertEquals(expected, result); |
|
1493 |
} |
|
1494 |
||
1495 |
@Test |
|
1496 |
public void testDropArguments() throws Throwable { |
|
1497 |
if (CAN_SKIP_WORKING) return; |
|
1498 |
startTest("dropArguments"); |
|
1499 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1500 |
for (int drop = 1; drop <= 4; drop++) { |
|
1501 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1502 |
testDropArguments(nargs, pos, drop); |
|
1503 |
} |
|
1504 |
} |
|
1505 |
} |
|
1506 |
} |
|
1507 |
||
1508 |
void testDropArguments(int nargs, int pos, int drop) throws Throwable { |
|
1509 |
countTest(); |
|
1510 |
MethodHandle target = ValueConversions.varargsArray(nargs); |
|
1511 |
Object[] args = randomArgs(target.type().parameterArray()); |
|
1512 |
MethodHandle target2 = MethodHandles.dropArguments(target, pos, |
|
1513 |
Collections.nCopies(drop, Object.class).toArray(new Class[0])); |
|
1514 |
List<Object> resList = Arrays.asList(args); |
|
1515 |
List<Object> argsToDrop = new ArrayList<Object>(resList); |
|
1516 |
for (int i = drop; i > 0; i--) { |
|
1517 |
argsToDrop.add(pos, "blort#"+i); |
|
1518 |
} |
|
1519 |
Object res2 = target2.invokeVarargs(argsToDrop); |
|
1520 |
Object res2List = Arrays.asList((Object[])res2); |
|
1521 |
//if (!resList.equals(res2List)) |
|
1522 |
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); |
|
1523 |
assertEquals(resList, res2List); |
|
1524 |
} |
|
1525 |
||
1526 |
@Test |
|
1527 |
public void testInvokers() throws Throwable { |
|
1528 |
if (CAN_SKIP_WORKING) return; |
|
1529 |
startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); |
|
1530 |
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker |
|
1531 |
Set<MethodType> done = new HashSet<MethodType>(); |
|
1532 |
for (int i = 0; i <= 6; i++) { |
|
1533 |
MethodType gtype = MethodType.genericMethodType(i); |
|
1534 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
1535 |
for (int j = -1; j < i; j++) { |
|
1536 |
MethodType type = gtype; |
|
1537 |
if (j < 0) |
|
1538 |
type = type.changeReturnType(argType); |
|
1539 |
else if (argType == void.class) |
|
1540 |
continue; |
|
1541 |
else |
|
1542 |
type = type.changeParameterType(j, argType); |
|
1543 |
if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5 |
|
1544 |
if (done.add(type)) |
|
1545 |
testInvokers(type); |
|
1546 |
MethodType vtype = type.changeReturnType(void.class); |
|
1547 |
if (done.add(vtype)) |
|
1548 |
testInvokers(vtype); |
|
1549 |
} |
|
1550 |
} |
|
1551 |
} |
|
1552 |
} |
|
1553 |
||
1554 |
public void testInvokers(MethodType type) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1555 |
if (verbosity >= 3) |
4537 | 1556 |
System.out.println("test invokers for "+type); |
1557 |
int nargs = type.parameterCount(); |
|
1558 |
boolean testRetCode = type.returnType() != void.class; |
|
1559 |
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee", |
|
1560 |
MethodType.genericMethodType(0, true)); |
|
1561 |
target = MethodHandles.collectArguments(target, type); |
|
1562 |
Object[] args = randomArgs(type.parameterArray()); |
|
1563 |
List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args)); |
|
1564 |
targetPlusArgs.add(0, target); |
|
1565 |
int code = (Integer) invokee(args); |
|
1566 |
Object log = logEntry("invokee", args); |
|
1567 |
assertEquals(log.hashCode(), code); |
|
1568 |
assertCalled("invokee", args); |
|
1569 |
MethodHandle inv; |
|
1570 |
Object result; |
|
1571 |
// exact invoker |
|
1572 |
countTest(); |
|
1573 |
calledLog.clear(); |
|
1574 |
inv = MethodHandles.exactInvoker(type); |
|
1575 |
result = inv.invokeVarargs(targetPlusArgs); |
|
1576 |
if (testRetCode) assertEquals(code, result); |
|
1577 |
assertCalled("invokee", args); |
|
1578 |
// generic invoker |
|
1579 |
countTest(); |
|
1580 |
inv = MethodHandles.genericInvoker(type); |
|
1581 |
if (nargs <= 3) { |
|
1582 |
calledLog.clear(); |
|
1583 |
switch (nargs) { |
|
1584 |
case 0: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1585 |
result = inv.invokeExact(target); |
4537 | 1586 |
break; |
1587 |
case 1: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1588 |
result = inv.invokeExact(target, args[0]); |
4537 | 1589 |
break; |
1590 |
case 2: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1591 |
result = inv.invokeExact(target, args[0], args[1]); |
4537 | 1592 |
break; |
1593 |
case 3: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1594 |
result = inv.invokeExact(target, args[0], args[1], args[2]); |
4537 | 1595 |
break; |
1596 |
} |
|
1597 |
if (testRetCode) assertEquals(code, result); |
|
1598 |
assertCalled("invokee", args); |
|
1599 |
} |
|
1600 |
calledLog.clear(); |
|
1601 |
result = inv.invokeVarargs(targetPlusArgs); |
|
1602 |
if (testRetCode) assertEquals(code, result); |
|
1603 |
assertCalled("invokee", args); |
|
1604 |
// varargs invoker #0 |
|
1605 |
calledLog.clear(); |
|
1606 |
inv = MethodHandles.varargsInvoker(type, 0); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1607 |
result = inv.invokeExact(target, args); |
4537 | 1608 |
if (testRetCode) assertEquals(code, result); |
1609 |
assertCalled("invokee", args); |
|
1610 |
if (nargs >= 1) { |
|
1611 |
// varargs invoker #1 |
|
1612 |
calledLog.clear(); |
|
1613 |
inv = MethodHandles.varargsInvoker(type, 1); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1614 |
result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
4537 | 1615 |
if (testRetCode) assertEquals(code, result); |
1616 |
assertCalled("invokee", args); |
|
1617 |
} |
|
1618 |
if (nargs >= 2) { |
|
1619 |
// varargs invoker #2 |
|
1620 |
calledLog.clear(); |
|
1621 |
inv = MethodHandles.varargsInvoker(type, 2); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1622 |
result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
4537 | 1623 |
if (testRetCode) assertEquals(code, result); |
1624 |
assertCalled("invokee", args); |
|
1625 |
} |
|
1626 |
if (nargs >= 3) { |
|
1627 |
// varargs invoker #3 |
|
1628 |
calledLog.clear(); |
|
1629 |
inv = MethodHandles.varargsInvoker(type, 3); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1630 |
result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
4537 | 1631 |
if (testRetCode) assertEquals(code, result); |
1632 |
assertCalled("invokee", args); |
|
1633 |
} |
|
1634 |
for (int k = 0; k <= nargs; k++) { |
|
1635 |
// varargs invoker #0..N |
|
1636 |
countTest(); |
|
1637 |
calledLog.clear(); |
|
1638 |
inv = MethodHandles.varargsInvoker(type, k); |
|
1639 |
List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs); |
|
1640 |
List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs); |
|
1641 |
Object[] tail = tailList.toArray(); |
|
1642 |
tailList.clear(); tailList.add(tail); |
|
1643 |
result = inv.invokeVarargs(targetPlusVarArgs); |
|
1644 |
if (testRetCode) assertEquals(code, result); |
|
1645 |
assertCalled("invokee", args); |
|
1646 |
} |
|
1647 |
// dynamic invoker |
|
1648 |
countTest(); |
|
1649 |
CallSite site = new CallSite(MethodHandlesTest.class, "foo", type); |
|
1650 |
inv = MethodHandles.dynamicInvoker(site); |
|
1651 |
site.setTarget(target); |
|
1652 |
calledLog.clear(); |
|
1653 |
result = inv.invokeVarargs(args); |
|
1654 |
if (testRetCode) assertEquals(code, result); |
|
1655 |
assertCalled("invokee", args); |
|
1656 |
} |
|
1657 |
||
1658 |
static Object invokee(Object... args) { |
|
1659 |
return called("invokee", args).hashCode(); |
|
1660 |
} |
|
1661 |
||
4535 | 1662 |
private static final String MISSING_ARG = "missingArg"; |
1663 |
static Object targetIfEquals() { |
|
1664 |
return called("targetIfEquals"); |
|
1665 |
} |
|
1666 |
static Object fallbackIfNotEquals() { |
|
1667 |
return called("fallbackIfNotEquals"); |
|
1668 |
} |
|
1669 |
static Object targetIfEquals(Object x) { |
|
1670 |
assertEquals(x, MISSING_ARG); |
|
1671 |
return called("targetIfEquals", x); |
|
1672 |
} |
|
1673 |
static Object fallbackIfNotEquals(Object x) { |
|
1674 |
assertFalse(x.toString(), x.equals(MISSING_ARG)); |
|
1675 |
return called("fallbackIfNotEquals", x); |
|
1676 |
} |
|
1677 |
static Object targetIfEquals(Object x, Object y) { |
|
1678 |
assertEquals(x, y); |
|
1679 |
return called("targetIfEquals", x, y); |
|
1680 |
} |
|
1681 |
static Object fallbackIfNotEquals(Object x, Object y) { |
|
1682 |
assertFalse(x.toString(), x.equals(y)); |
|
1683 |
return called("fallbackIfNotEquals", x, y); |
|
1684 |
} |
|
1685 |
static Object targetIfEquals(Object x, Object y, Object z) { |
|
1686 |
assertEquals(x, y); |
|
1687 |
return called("targetIfEquals", x, y, z); |
|
1688 |
} |
|
1689 |
static Object fallbackIfNotEquals(Object x, Object y, Object z) { |
|
1690 |
assertFalse(x.toString(), x.equals(y)); |
|
1691 |
return called("fallbackIfNotEquals", x, y, z); |
|
1692 |
} |
|
1693 |
||
4537 | 1694 |
@Test |
1695 |
public void testGuardWithTest() throws Throwable { |
|
1696 |
if (CAN_SKIP_WORKING) return; |
|
1697 |
startTest("guardWithTest"); |
|
1698 |
for (int nargs = 0; nargs <= 3; nargs++) { |
|
1699 |
if (nargs != 2) continue; // FIXME: test more later |
|
1700 |
testGuardWithTest(nargs, Object.class); |
|
1701 |
testGuardWithTest(nargs, String.class); |
|
1702 |
} |
|
1703 |
} |
|
1704 |
void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable { |
|
1705 |
countTest(); |
|
1706 |
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); |
|
1707 |
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs)); |
|
1708 |
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs)); |
|
1709 |
while (test.type().parameterCount() < nargs) |
|
1710 |
test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class); |
|
1711 |
while (test.type().parameterCount() > nargs) |
|
1712 |
test = MethodHandles.insertArguments(test, 0, MISSING_ARG); |
|
1713 |
if (argClass != Object.class) { |
|
1714 |
test = changeArgTypes(test, argClass); |
|
1715 |
target = changeArgTypes(target, argClass); |
|
1716 |
fallback = changeArgTypes(fallback, argClass); |
|
1717 |
} |
|
1718 |
MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback); |
|
1719 |
assertEquals(target.type(), mh.type()); |
|
1720 |
Object[][] argLists = { |
|
1721 |
{ }, |
|
1722 |
{ "foo" }, { MISSING_ARG }, |
|
1723 |
{ "foo", "foo" }, { "foo", "bar" }, |
|
1724 |
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" } |
|
1725 |
}; |
|
1726 |
for (Object[] argList : argLists) { |
|
1727 |
if (argList.length != nargs) continue; |
|
1728 |
boolean equals; |
|
1729 |
switch (nargs) { |
|
1730 |
case 0: equals = true; break; |
|
1731 |
case 1: equals = MISSING_ARG.equals(argList[0]); break; |
|
1732 |
default: equals = argList[0].equals(argList[1]); break; |
|
1733 |
} |
|
1734 |
String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1735 |
if (verbosity >= 3) |
4537 | 1736 |
System.out.println(logEntry(willCall, argList)); |
1737 |
Object result = mh.invokeVarargs(argList); |
|
1738 |
assertCalled(willCall, argList); |
|
1739 |
} |
|
1740 |
} |
|
1741 |
||
1742 |
@Test |
|
1743 |
public void testCatchException() throws Throwable { |
|
1744 |
if (CAN_SKIP_WORKING) return; |
|
1745 |
startTest("catchException"); |
|
1746 |
for (int nargs = 2; nargs <= 6; nargs++) { |
|
1747 |
for (int ti = 0; ti <= 1; ti++) { |
|
1748 |
boolean throwIt = (ti != 0); |
|
1749 |
testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs); |
|
1750 |
testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs); |
|
1751 |
testCatchException(String.class, new LinkageError("testing"), throwIt, nargs); |
|
1752 |
} |
|
1753 |
} |
|
1754 |
} |
|
1755 |
||
1756 |
private static <T extends Throwable> |
|
1757 |
Object throwOrReturn(Object normal, T exception) throws T { |
|
1758 |
if (exception != null) throw exception; |
|
1759 |
return normal; |
|
1760 |
} |
|
1761 |
||
1762 |
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable { |
|
1763 |
countTest(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1764 |
if (verbosity >= 3) |
4537 | 1765 |
System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs); |
1766 |
Class<? extends Throwable> exType = thrown.getClass(); |
|
1767 |
MethodHandle throwOrReturn |
|
1768 |
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn", |
|
1769 |
MethodType.methodType(Object.class, Object.class, Throwable.class)); |
|
1770 |
MethodHandle thrower = throwOrReturn; |
|
1771 |
while (thrower.type().parameterCount() < nargs) |
|
1772 |
thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class); |
|
1773 |
MethodHandle target = MethodHandles.catchException(thrower, |
|
1774 |
thrown.getClass(), ValueConversions.varargsList(1+nargs)); |
|
1775 |
assertEquals(thrower.type(), target.type()); |
|
1776 |
//System.out.println("catching with "+target+" : "+throwOrReturn); |
|
1777 |
Object[] args = randomArgs(nargs, Object.class); |
|
1778 |
args[1] = (throwIt ? thrown : null); |
|
1779 |
Object returned = target.invokeVarargs(args); |
|
1780 |
//System.out.println("return from "+target+" : "+returned); |
|
1781 |
if (!throwIt) { |
|
1782 |
assertSame(args[0], returned); |
|
1783 |
} else { |
|
1784 |
List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args)); |
|
1785 |
catchArgs.add(0, thrown); |
|
1786 |
assertEquals(catchArgs, returned); |
|
1787 |
} |
|
1788 |
} |
|
1789 |
||
1790 |
@Test |
|
1791 |
public void testThrowException() throws Throwable { |
|
1792 |
if (CAN_SKIP_WORKING) return; |
|
1793 |
startTest("throwException"); |
|
1794 |
testThrowException(int.class, new ClassCastException("testing")); |
|
1795 |
testThrowException(void.class, new java.io.IOException("testing")); |
|
1796 |
testThrowException(String.class, new LinkageError("testing")); |
|
1797 |
} |
|
1798 |
||
1799 |
void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable { |
|
1800 |
countTest(); |
|
1801 |
Class<? extends Throwable> exType = thrown.getClass(); |
|
1802 |
MethodHandle target = MethodHandles.throwException(returnType, exType); |
|
1803 |
//System.out.println("throwing with "+target+" : "+thrown); |
|
1804 |
MethodType expectedType = MethodType.methodType(returnType, exType); |
|
1805 |
assertEquals(expectedType, target.type()); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1806 |
target = MethodHandles.convertArguments(target, target.type().generic()); |
4537 | 1807 |
Throwable caught = null; |
1808 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1809 |
Object res = target.invokeExact((Object) thrown); |
4537 | 1810 |
fail("got "+res+" instead of throwing "+thrown); |
1811 |
} catch (Throwable ex) { |
|
1812 |
if (ex != thrown) { |
|
1813 |
if (ex instanceof Error) throw (Error)ex; |
|
1814 |
if (ex instanceof RuntimeException) throw (RuntimeException)ex; |
|
1815 |
} |
|
1816 |
caught = ex; |
|
1817 |
} |
|
1818 |
assertSame(thrown, caught); |
|
1819 |
} |
|
1820 |
||
1821 |
@Test |
|
1822 |
public void testCastFailure() throws Throwable { |
|
1823 |
if (CAN_SKIP_WORKING) return; |
|
1824 |
startTest("testCastFailure"); |
|
1825 |
testCastFailure("cast/argument", 11000); |
|
1826 |
testCastFailure("unbox/argument", 11000); |
|
1827 |
testCastFailure("cast/return", 11000); |
|
1828 |
testCastFailure("unbox/return", 11000); |
|
1829 |
} |
|
1830 |
||
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1831 |
static class Surprise implements MethodHandleProvider { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1832 |
public MethodHandle asMethodHandle() { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1833 |
return VALUE.bindTo(this); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1834 |
} |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1835 |
public MethodHandle asMethodHandle(MethodType type) { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1836 |
return asMethodHandle().asType(type); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1837 |
} |
4537 | 1838 |
Object value(Object x) { |
1839 |
trace("value", x); |
|
1840 |
if (boo != null) return boo; |
|
1841 |
return x; |
|
1842 |
} |
|
1843 |
Object boo; |
|
1844 |
void boo(Object x) { boo = x; } |
|
1845 |
||
1846 |
static void trace(String x, Object y) { |
|
1847 |
if (verbosity > 8) System.out.println(x+"="+y); |
|
1848 |
} |
|
1849 |
static Object refIdentity(Object x) { trace("ref.x", x); return x; } |
|
1850 |
static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } |
|
1851 |
static int intIdentity(int x) { trace("int.x", x); return x; } |
|
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1852 |
static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY; |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1853 |
static { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1854 |
try { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1855 |
VALUE = PRIVATE.findVirtual( |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1856 |
Surprise.class, "value", |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1857 |
MethodType.methodType(Object.class, Object.class)); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1858 |
REF_IDENTITY = PRIVATE.findStatic( |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1859 |
Surprise.class, "refIdentity", |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1860 |
MethodType.methodType(Object.class, Object.class)); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1861 |
BOX_IDENTITY = PRIVATE.findStatic( |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1862 |
Surprise.class, "boxIdentity", |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1863 |
MethodType.methodType(Integer.class, Integer.class)); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1864 |
INT_IDENTITY = PRIVATE.findStatic( |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1865 |
Surprise.class, "intIdentity", |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1866 |
MethodType.methodType(int.class, int.class)); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1867 |
} catch (Exception ex) { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1868 |
throw new RuntimeException(ex); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1869 |
} |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1870 |
} |
4537 | 1871 |
} |
1872 |
||
1873 |
void testCastFailure(String mode, int okCount) throws Throwable { |
|
1874 |
countTest(false); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1875 |
if (verbosity > 2) System.out.println("mode="+mode); |
4537 | 1876 |
Surprise boo = new Surprise(); |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1877 |
MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0; |
4537 | 1878 |
if (mode.endsWith("/return")) { |
1879 |
if (mode.equals("unbox/return")) { |
|
1880 |
// fail on return to ((Integer)surprise).intValue |
|
1881 |
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class)); |
|
1882 |
identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class)); |
|
1883 |
} else if (mode.equals("cast/return")) { |
|
1884 |
// fail on return to (Integer)surprise |
|
1885 |
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class)); |
|
1886 |
identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class)); |
|
1887 |
} |
|
1888 |
} else if (mode.endsWith("/argument")) { |
|
1889 |
MethodHandle callee = null; |
|
1890 |
if (mode.equals("unbox/argument")) { |
|
1891 |
// fail on handing surprise to int argument |
|
1892 |
callee = Surprise.INT_IDENTITY; |
|
1893 |
} else if (mode.equals("cast/argument")) { |
|
1894 |
// fail on handing surprise to Integer argument |
|
1895 |
callee = Surprise.BOX_IDENTITY; |
|
1896 |
} |
|
1897 |
if (callee != null) { |
|
1898 |
callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1)); |
|
1899 |
surprise = MethodHandles.filterArguments(callee, surprise); |
|
1900 |
identity = MethodHandles.filterArguments(callee, identity); |
|
1901 |
} |
|
1902 |
} |
|
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
7051
diff
changeset
|
1903 |
assertNotSame(mode, surprise, surprise0); |
4537 | 1904 |
identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1)); |
1905 |
surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1)); |
|
1906 |
Object x = 42; |
|
1907 |
for (int i = 0; i < okCount; i++) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1908 |
Object y = identity.invokeExact(x); |
4537 | 1909 |
assertEquals(x, y); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1910 |
Object z = surprise.invokeExact(x); |
4537 | 1911 |
assertEquals(x, z); |
1912 |
} |
|
1913 |
boo.boo("Boo!"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1914 |
Object y = identity.invokeExact(x); |
4537 | 1915 |
assertEquals(x, y); |
1916 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1917 |
Object z = surprise.invokeExact(x); |
4537 | 1918 |
System.out.println("Failed to throw; got z="+z); |
1919 |
assertTrue(false); |
|
1920 |
} catch (Exception ex) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1921 |
if (verbosity > 2) |
4537 | 1922 |
System.out.println("caught "+ex); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1923 |
if (verbosity > 3) |
4537 | 1924 |
ex.printStackTrace(); |
1925 |
assertTrue(ex instanceof ClassCastException |
|
1926 |
// FIXME: accept only one of the two for any given unit test |
|
1927 |
|| ex instanceof WrongMethodTypeException |
|
1928 |
); |
|
1929 |
} |
|
1930 |
} |
|
1931 |
||
5723
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1932 |
static Example userMethod(Object o, String s, int i) { |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1933 |
called("userMethod", o, s, i); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1934 |
return null; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1935 |
} |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1936 |
|
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1937 |
@Test |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1938 |
public void testUserClassInSignature() throws Throwable { |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1939 |
if (CAN_SKIP_WORKING) return; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1940 |
startTest("testUserClassInSignature"); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1941 |
Lookup lookup = MethodHandles.lookup(); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1942 |
String name; MethodType mt; MethodHandle mh; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1943 |
Object[] args; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1944 |
|
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1945 |
// Try a static method. |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1946 |
name = "userMethod"; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1947 |
mt = MethodType.methodType(Example.class, Object.class, String.class, int.class); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1948 |
mh = lookup.findStatic(lookup.lookupClass(), name, mt); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1949 |
assertEquals(mt, mh.type()); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1950 |
assertEquals(Example.class, mh.type().returnType()); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1951 |
args = randomArgs(mh.type().parameterArray()); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1952 |
mh.invokeVarargs(args); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1953 |
assertCalled(name, args); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1954 |
|
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1955 |
// Try a virtual method. |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1956 |
name = "v2"; |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1957 |
mt = MethodType.methodType(Object.class, Object.class, int.class); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1958 |
mh = lookup.findVirtual(Example.class, name, mt); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1959 |
assertEquals(mt, mh.type().dropParameterTypes(0,1)); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1960 |
assertTrue(mh.type().parameterList().contains(Example.class)); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1961 |
args = randomArgs(mh.type().parameterArray()); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1962 |
mh.invokeVarargs(args); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1963 |
assertCalled(name, args); |
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
1964 |
} |
7053 | 1965 |
|
1966 |
static void runForRunnable() { |
|
1967 |
called("runForRunnable"); |
|
1968 |
} |
|
1969 |
private interface Fooable { |
|
1970 |
Object foo(Fooable x, Object y); |
|
1971 |
// this is for randomArg: |
|
1972 |
public class Impl implements Fooable { |
|
1973 |
public Object foo(Fooable x, Object y) { |
|
1974 |
throw new RuntimeException("do not call"); |
|
1975 |
} |
|
1976 |
final String name; |
|
1977 |
public Impl() { name = "Fooable#"+nextArg(); } |
|
1978 |
@Override public String toString() { return name; } |
|
1979 |
} |
|
1980 |
} |
|
1981 |
static Object fooForFooable(Fooable x, Object y) { |
|
1982 |
return called("fooForFooable", x, y); |
|
1983 |
} |
|
1984 |
private static class MyCheckedException extends Exception { |
|
1985 |
} |
|
1986 |
private interface WillThrow { |
|
1987 |
void willThrow() throws MyCheckedException; |
|
1988 |
} |
|
1989 |
||
1990 |
@Test |
|
1991 |
public void testAsInstance() throws Throwable { |
|
1992 |
if (CAN_SKIP_WORKING) return; |
|
1993 |
Lookup lookup = MethodHandles.lookup(); |
|
1994 |
{ |
|
1995 |
MethodType mt = MethodType.methodType(void.class); |
|
1996 |
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt); |
|
1997 |
Runnable proxy = MethodHandles.asInstance(mh, Runnable.class); |
|
1998 |
proxy.run(); |
|
1999 |
assertCalled("runForRunnable"); |
|
2000 |
} |
|
2001 |
{ |
|
2002 |
MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class); |
|
2003 |
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt); |
|
2004 |
Fooable proxy = MethodHandles.asInstance(mh, Fooable.class); |
|
2005 |
Object[] args = randomArgs(mt.parameterArray()); |
|
2006 |
Object result = proxy.foo((Fooable) args[0], args[1]); |
|
2007 |
assertCalled("fooForFooable", args); |
|
2008 |
assertEquals(result, logEntry("fooForFooable", args)); |
|
2009 |
} |
|
2010 |
for (Throwable ex : new Throwable[] { new NullPointerException("ok"), |
|
2011 |
new InternalError("ok"), |
|
2012 |
new Throwable("fail"), |
|
2013 |
new Exception("fail"), |
|
2014 |
new MyCheckedException() |
|
2015 |
}) { |
|
2016 |
MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class); |
|
2017 |
mh = MethodHandles.insertArguments(mh, 0, ex); |
|
2018 |
WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class); |
|
2019 |
try { |
|
2020 |
proxy.willThrow(); |
|
2021 |
System.out.println("Failed to throw: "+ex); |
|
2022 |
assertTrue(false); |
|
2023 |
} catch (Throwable ex1) { |
|
2024 |
if (verbosity > 2) { |
|
2025 |
System.out.println("throw "+ex); |
|
2026 |
System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1)); |
|
2027 |
} |
|
2028 |
if (ex instanceof RuntimeException || |
|
2029 |
ex instanceof Error) { |
|
2030 |
assertSame("must pass unchecked exception out without wrapping", ex, ex1); |
|
2031 |
} else if (ex instanceof MyCheckedException) { |
|
2032 |
assertSame("must pass declared exception out without wrapping", ex, ex1); |
|
2033 |
} else { |
|
2034 |
assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1); |
|
2035 |
UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1; |
|
2036 |
assertSame(ex, utex.getCause()); |
|
2037 |
} |
|
2038 |
} |
|
2039 |
} |
|
2040 |
// Test error checking: |
|
2041 |
MethodHandle genericMH = ValueConversions.varargsArray(0); |
|
2042 |
genericMH = MethodHandles.convertArguments(genericMH, genericMH.type().generic()); |
|
2043 |
for (Class<?> sam : new Class[] { Runnable.class, |
|
2044 |
Fooable.class, |
|
2045 |
Iterable.class }) { |
|
2046 |
try { |
|
2047 |
// Must throw, because none of these guys has generic type. |
|
2048 |
MethodHandles.asInstance(genericMH, sam); |
|
2049 |
System.out.println("Failed to throw"); |
|
2050 |
assertTrue(false); |
|
2051 |
} catch (IllegalArgumentException ex) { |
|
2052 |
} |
|
2053 |
} |
|
2054 |
for (Class<?> nonSAM : new Class[] { Object.class, |
|
2055 |
String.class, |
|
2056 |
CharSequence.class, |
|
2057 |
Example.class }) { |
|
2058 |
try { |
|
2059 |
MethodHandles.asInstance(ValueConversions.varargsArray(0), nonSAM); |
|
2060 |
System.out.println("Failed to throw"); |
|
2061 |
assertTrue(false); |
|
2062 |
} catch (IllegalArgumentException ex) { |
|
2063 |
} |
|
2064 |
} |
|
2065 |
} |
|
4535 | 2066 |
} |
2067 |
// Local abbreviated copy of sun.dyn.util.ValueConversions |
|
2068 |
class ValueConversions { |
|
2069 |
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); |
|
2070 |
private static final Object[] NO_ARGS_ARRAY = {}; |
|
2071 |
private static Object[] makeArray(Object... args) { return args; } |
|
2072 |
private static Object[] array() { return NO_ARGS_ARRAY; } |
|
2073 |
private static Object[] array(Object a0) |
|
2074 |
{ return makeArray(a0); } |
|
2075 |
private static Object[] array(Object a0, Object a1) |
|
2076 |
{ return makeArray(a0, a1); } |
|
2077 |
private static Object[] array(Object a0, Object a1, Object a2) |
|
2078 |
{ return makeArray(a0, a1, a2); } |
|
2079 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3) |
|
2080 |
{ return makeArray(a0, a1, a2, a3); } |
|
2081 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2082 |
Object a4) |
|
2083 |
{ return makeArray(a0, a1, a2, a3, a4); } |
|
2084 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2085 |
Object a4, Object a5) |
|
2086 |
{ return makeArray(a0, a1, a2, a3, a4, a5); } |
|
2087 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2088 |
Object a4, Object a5, Object a6) |
|
2089 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6); } |
|
2090 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2091 |
Object a4, Object a5, Object a6, Object a7) |
|
2092 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } |
|
2093 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2094 |
Object a4, Object a5, Object a6, Object a7, |
|
2095 |
Object a8) |
|
2096 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } |
|
2097 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
2098 |
Object a4, Object a5, Object a6, Object a7, |
|
2099 |
Object a8, Object a9) |
|
2100 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } |
|
2101 |
static MethodHandle[] makeArrays() { |
|
2102 |
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>(); |
|
2103 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
2104 |
for (;;) { |
|
2105 |
int nargs = arrays.size(); |
|
4537 | 2106 |
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class); |
4535 | 2107 |
String name = "array"; |
2108 |
MethodHandle array = null; |
|
2109 |
try { |
|
2110 |
array = lookup.findStatic(ValueConversions.class, name, type); |
|
2111 |
} catch (NoAccessException ex) { |
|
2112 |
} |
|
2113 |
if (array == null) break; |
|
2114 |
arrays.add(array); |
|
2115 |
} |
|
2116 |
assert(arrays.size() == 11); // current number of methods |
|
2117 |
return arrays.toArray(new MethodHandle[0]); |
|
2118 |
} |
|
2119 |
static final MethodHandle[] ARRAYS = makeArrays(); |
|
2120 |
||
2121 |
/** Return a method handle that takes the indicated number of Object |
|
2122 |
* arguments and returns an Object array of them, as if for varargs. |
|
2123 |
*/ |
|
2124 |
public static MethodHandle varargsArray(int nargs) { |
|
2125 |
if (nargs < ARRAYS.length) |
|
2126 |
return ARRAYS[nargs]; |
|
2127 |
// else need to spin bytecode or do something else fancy |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
2128 |
throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs); |
4535 | 2129 |
} |
4537 | 2130 |
|
2131 |
private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); |
|
2132 |
private static List<Object> makeList(Object... args) { return Arrays.asList(args); } |
|
2133 |
private static List<Object> list() { return NO_ARGS_LIST; } |
|
2134 |
private static List<Object> list(Object a0) |
|
2135 |
{ return makeList(a0); } |
|
2136 |
private static List<Object> list(Object a0, Object a1) |
|
2137 |
{ return makeList(a0, a1); } |
|
2138 |
private static List<Object> list(Object a0, Object a1, Object a2) |
|
2139 |
{ return makeList(a0, a1, a2); } |
|
2140 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3) |
|
2141 |
{ return makeList(a0, a1, a2, a3); } |
|
2142 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2143 |
Object a4) |
|
2144 |
{ return makeList(a0, a1, a2, a3, a4); } |
|
2145 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2146 |
Object a4, Object a5) |
|
2147 |
{ return makeList(a0, a1, a2, a3, a4, a5); } |
|
2148 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2149 |
Object a4, Object a5, Object a6) |
|
2150 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6); } |
|
2151 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2152 |
Object a4, Object a5, Object a6, Object a7) |
|
2153 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } |
|
2154 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2155 |
Object a4, Object a5, Object a6, Object a7, |
|
2156 |
Object a8) |
|
2157 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } |
|
2158 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
2159 |
Object a4, Object a5, Object a6, Object a7, |
|
2160 |
Object a8, Object a9) |
|
2161 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } |
|
2162 |
static MethodHandle[] makeLists() { |
|
2163 |
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>(); |
|
2164 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
2165 |
for (;;) { |
|
2166 |
int nargs = arrays.size(); |
|
2167 |
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class); |
|
2168 |
String name = "list"; |
|
2169 |
MethodHandle array = null; |
|
2170 |
try { |
|
2171 |
array = lookup.findStatic(ValueConversions.class, name, type); |
|
2172 |
} catch (NoAccessException ex) { |
|
2173 |
} |
|
2174 |
if (array == null) break; |
|
2175 |
arrays.add(array); |
|
2176 |
} |
|
2177 |
assert(arrays.size() == 11); // current number of methods |
|
2178 |
return arrays.toArray(new MethodHandle[0]); |
|
2179 |
} |
|
2180 |
static final MethodHandle[] LISTS = makeLists(); |
|
2181 |
||
2182 |
/** Return a method handle that takes the indicated number of Object |
|
2183 |
* arguments and returns List. |
|
2184 |
*/ |
|
2185 |
public static MethodHandle varargsList(int nargs) { |
|
2186 |
if (nargs < LISTS.length) |
|
2187 |
return LISTS[nargs]; |
|
2188 |
// else need to spin bytecode or do something else fancy |
|
2189 |
throw new UnsupportedOperationException("NYI"); |
|
2190 |
} |
|
4535 | 2191 |
} |
2192 |
// This guy tests access from outside the same package member, but inside |
|
2193 |
// the package itself. |
|
2194 |
class PackageSibling { |
|
2195 |
static Lookup lookup() { |
|
2196 |
return MethodHandles.lookup(); |
|
2197 |
} |
|
2198 |
} |