Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java
47791 views
1
/*
2
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
package test.java.lang.invoke.MethodHandles;
24
25
import com.oracle.testlibrary.jsr292.Helper;
26
import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
27
import jdk.testlibrary.Asserts;
28
import jdk.testlibrary.TimeLimitedRunner;
29
import jdk.testlibrary.Utils;
30
31
import java.lang.invoke.MethodHandle;
32
import java.lang.invoke.MethodHandles;
33
import java.lang.invoke.MethodType;
34
import java.lang.reflect.Array;
35
import java.util.*;
36
import java.util.function.BiFunction;
37
import java.util.function.Function;
38
import java.util.function.Supplier;
39
40
/* @test
41
* @library /lib/testlibrary/jsr292 /lib/testlibrary/
42
* @compile CatchExceptionTest.java
43
* @run main/othervm -esa test.java.lang.invoke.MethodHandles.CatchExceptionTest
44
* @key randomness
45
*/
46
public class CatchExceptionTest {
47
48
private static final List<Class<?>> ARGS_CLASSES;
49
protected static final int MAX_ARITY = Helper.MAX_ARITY - 1;
50
51
static {
52
Class<?> classes[] = {
53
Object.class,
54
long.class,
55
int.class,
56
byte.class,
57
Integer[].class,
58
double[].class,
59
String.class,
60
};
61
ARGS_CLASSES = Collections.unmodifiableList(
62
Helper.randomClasses(classes, MAX_ARITY));
63
}
64
65
private final TestCase testCase;
66
private final int nargs;
67
private final int argsCount;
68
private final MethodHandle catcher;
69
private int dropped;
70
private MethodHandle thrower;
71
72
public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount,
73
final int catchDrops) {
74
this.testCase = testCase;
75
this.dropped = catchDrops;
76
MethodHandle thrower = testCase.thrower;
77
int throwerLen = thrower.type().parameterCount();
78
List<Class<?>> classes;
79
int extra = Math.max(0, argsCount - throwerLen);
80
classes = getThrowerParams(isVararg, extra);
81
this.argsCount = throwerLen + classes.size();
82
thrower = Helper.addTrailingArgs(thrower, this.argsCount, classes);
83
if (isVararg && argsCount > throwerLen) {
84
MethodType mt = thrower.type();
85
Class<?> lastParam = mt.parameterType(mt.parameterCount() - 1);
86
thrower = thrower.asVarargsCollector(lastParam);
87
}
88
this.thrower = thrower;
89
this.dropped = Math.min(this.argsCount, catchDrops);
90
catcher = testCase.getCatcher(getCatcherParams());
91
nargs = Math.max(2, this.argsCount);
92
}
93
94
public static void main(String[] args) throws Throwable {
95
CodeCacheOverflowProcessor.runMHTest(CatchExceptionTest::test);
96
}
97
98
public static void test() throws Throwable {
99
System.out.println("classes = " + ARGS_CLASSES);
100
TestFactory factory = new TestFactory();
101
long timeout = Helper.IS_THOROUGH ? 0L : Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT);
102
// subtract vm init time and reserve time for vm exit
103
timeout *= 0.9;
104
TimeLimitedRunner runner = new TimeLimitedRunner(timeout, 2.0d,
105
() -> {
106
CatchExceptionTest test = factory.nextTest();
107
if (test != null) {
108
test.runTest();
109
return true;
110
}
111
return false;
112
});
113
for (CatchExceptionTest test : TestFactory.MANDATORY_TEST_CASES) {
114
test.runTest();
115
}
116
runner.call();
117
}
118
119
private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) {
120
return Helper.getParams(ARGS_CLASSES, isVararg, argsCount);
121
}
122
123
private List<Class<?>> getCatcherParams() {
124
int catchArgc = 1 + this.argsCount - dropped;
125
List<Class<?>> result = new ArrayList<>(
126
thrower.type().parameterList().subList(0, catchArgc - 1));
127
// prepend throwable
128
result.add(0, testCase.throwableClass);
129
return result;
130
}
131
132
private void runTest() {
133
if (Helper.IS_VERBOSE) {
134
System.out.printf("CatchException(%s, isVararg=%b argsCount=%d "
135
+ "dropped=%d)%n",
136
testCase, thrower.isVarargsCollector(),
137
argsCount, dropped);
138
}
139
140
Helper.clear();
141
142
Object[] args = Helper.randomArgs(
143
argsCount, thrower.type().parameterArray());
144
Object arg0 = Helper.MISSING_ARG;
145
Object arg1 = testCase.thrown;
146
if (argsCount > 0) {
147
arg0 = args[0];
148
}
149
if (argsCount > 1) {
150
args[1] = arg1;
151
}
152
Asserts.assertEQ(nargs, thrower.type().parameterCount());
153
if (argsCount < nargs) {
154
Object[] appendArgs = {arg0, arg1};
155
appendArgs = Arrays.copyOfRange(appendArgs, argsCount, nargs);
156
thrower = MethodHandles.insertArguments(
157
thrower, argsCount, appendArgs);
158
}
159
Asserts.assertEQ(argsCount, thrower.type().parameterCount());
160
161
MethodHandle target = MethodHandles.catchException(
162
testCase.filter(thrower), testCase.throwableClass,
163
testCase.filter(catcher));
164
165
Asserts.assertEQ(thrower.type(), target.type());
166
Asserts.assertEQ(argsCount, target.type().parameterCount());
167
168
Object returned;
169
try {
170
returned = target.invokeWithArguments(args);
171
} catch (Throwable ex) {
172
if (CodeCacheOverflowProcessor.isThrowableCausedByVME(ex)) {
173
// This error will be treated by CodeCacheOverflowProcessor
174
// to prevent the test from failing because of code cache overflow.
175
throw new Error(ex);
176
}
177
testCase.assertCatch(ex);
178
returned = ex;
179
}
180
181
testCase.assertReturn(returned, arg0, arg1, dropped, args);
182
}
183
}
184
185
class TestFactory {
186
public static final List<CatchExceptionTest> MANDATORY_TEST_CASES = new ArrayList<>();
187
188
private static final int MIN_TESTED_ARITY = 10;
189
190
static {
191
for (int[] args : new int[][]{
192
{0, 0},
193
{MIN_TESTED_ARITY, 0},
194
{MIN_TESTED_ARITY, MIN_TESTED_ARITY},
195
{CatchExceptionTest.MAX_ARITY, 0},
196
{CatchExceptionTest.MAX_ARITY, CatchExceptionTest.MAX_ARITY},
197
}) {
198
MANDATORY_TEST_CASES.addAll(createTests(args[0], args[1]));
199
}
200
}
201
202
private int count;
203
private int args;
204
private int dropArgs;
205
private int currentMaxDrops;
206
private int maxArgs;
207
private int maxDrops;
208
private int constructor;
209
private int constructorSize;
210
private boolean isVararg;
211
212
public TestFactory() {
213
if (Helper.IS_THOROUGH) {
214
maxArgs = maxDrops = CatchExceptionTest.MAX_ARITY;
215
} else {
216
maxArgs = MIN_TESTED_ARITY
217
+ Helper.RNG.nextInt(CatchExceptionTest.MAX_ARITY
218
- MIN_TESTED_ARITY)
219
+ 1;
220
maxDrops = MIN_TESTED_ARITY
221
+ Helper.RNG.nextInt(maxArgs - MIN_TESTED_ARITY)
222
+ 1;
223
args = 1;
224
}
225
226
System.out.printf("maxArgs = %d%nmaxDrops = %d%n", maxArgs, maxDrops);
227
constructorSize = TestCase.CONSTRUCTORS.size();
228
}
229
230
private static List<CatchExceptionTest> createTests(int argsCount,
231
int catchDrops) {
232
if (catchDrops > argsCount || argsCount < 0 || catchDrops < 0) {
233
throw new IllegalArgumentException("argsCount = " + argsCount
234
+ ", catchDrops = " + catchDrops
235
);
236
}
237
List<CatchExceptionTest> result = new ArrayList<>(
238
TestCase.CONSTRUCTORS.size());
239
for (Supplier<TestCase> constructor : TestCase.CONSTRUCTORS) {
240
result.add(new CatchExceptionTest(constructor.get(),
241
/* isVararg = */ true,
242
argsCount,
243
catchDrops));
244
result.add(new CatchExceptionTest(constructor.get(),
245
/* isVararg = */ false,
246
argsCount,
247
catchDrops));
248
}
249
return result;
250
}
251
252
/**
253
* @return next test from test matrix: {varArgs, noVarArgs} x
254
* TestCase.rtypes x TestCase.THROWABLES x {1, .., maxArgs } x
255
* {0, .., maxDrops}
256
*/
257
public CatchExceptionTest nextTest() {
258
if (constructor < constructorSize) {
259
return createTest();
260
}
261
constructor = 0;
262
count++;
263
if (!Helper.IS_THOROUGH && count > Helper.TEST_LIMIT) {
264
System.out.println("test limit is exceeded");
265
return null;
266
}
267
if (dropArgs <= currentMaxDrops) {
268
if (dropArgs == 0) {
269
if (Helper.IS_THOROUGH || Helper.RNG.nextBoolean()) {
270
++dropArgs;
271
return createTest();
272
} else if (Helper.IS_VERBOSE) {
273
System.out.printf(
274
"argsCount=%d : \"drop\" scenarios are skipped%n",
275
args);
276
}
277
} else {
278
++dropArgs;
279
return createTest();
280
}
281
}
282
283
if (args < maxArgs) {
284
dropArgs = 0;
285
currentMaxDrops = Math.min(args, maxDrops);
286
++args;
287
return createTest();
288
}
289
return null;
290
}
291
292
private CatchExceptionTest createTest() {
293
if (!Helper.IS_THOROUGH) {
294
return new CatchExceptionTest(
295
TestCase.CONSTRUCTORS.get(constructor++).get(),
296
Helper.RNG.nextBoolean(), args, dropArgs);
297
} else {
298
if (isVararg) {
299
isVararg = false;
300
return new CatchExceptionTest(
301
TestCase.CONSTRUCTORS.get(constructor++).get(),
302
isVararg, args, dropArgs);
303
} else {
304
isVararg = true;
305
return new CatchExceptionTest(
306
TestCase.CONSTRUCTORS.get(constructor).get(),
307
isVararg, args, dropArgs);
308
}
309
}
310
}
311
}
312
313
class TestCase<T> {
314
private static enum ThrowMode {
315
NOTHING,
316
CAUGHT,
317
UNCAUGHT,
318
ADAPTER
319
}
320
321
@SuppressWarnings("unchecked")
322
public static final List<Supplier<TestCase>> CONSTRUCTORS;
323
private static final MethodHandle FAKE_IDENTITY;
324
private static final MethodHandle THROW_OR_RETURN;
325
private static final MethodHandle CATCHER;
326
327
static {
328
try {
329
MethodHandles.Lookup lookup = MethodHandles.lookup();
330
THROW_OR_RETURN = lookup.findStatic(
331
TestCase.class,
332
"throwOrReturn",
333
MethodType.methodType(Object.class, Object.class,
334
Throwable.class)
335
);
336
CATCHER = lookup.findStatic(
337
TestCase.class,
338
"catcher",
339
MethodType.methodType(Object.class, Object.class));
340
FAKE_IDENTITY = lookup.findVirtual(
341
TestCase.class, "fakeIdentity",
342
MethodType.methodType(Object.class, Object.class));
343
344
} catch (NoSuchMethodException | IllegalAccessException e) {
345
throw new Error(e);
346
}
347
PartialConstructor[] constructors = {
348
create(Object.class, Object.class::cast),
349
create(String.class, Objects::toString),
350
create(int[].class, x -> new int[]{Objects.hashCode(x)}),
351
create(long.class,
352
x -> Objects.hashCode(x) & (-1L >>> 32)),
353
create(void.class, TestCase::noop)};
354
Throwable[] throwables = {
355
new ClassCastException("testing"),
356
new java.io.IOException("testing"),
357
new LinkageError("testing")};
358
List<Supplier<TestCase>> list = new ArrayList<>(constructors.length *
359
throwables.length * ThrowMode.values().length);
360
//noinspection unchecked
361
for (PartialConstructor f : constructors) {
362
for (ThrowMode mode : ThrowMode.values()) {
363
for (Throwable t : throwables) {
364
list.add(f.apply(mode, t));
365
}
366
}
367
}
368
CONSTRUCTORS = Collections.unmodifiableList(list);
369
}
370
371
public final Class<T> rtype;
372
public final ThrowMode throwMode;
373
public final Throwable thrown;
374
public final Class<? extends Throwable> throwableClass;
375
/**
376
* MH which takes 2 args (Object,Throwable), 1st is the return value,
377
* 2nd is the exception which will be thrown, if it's supposed in current
378
* {@link #throwMode}.
379
*/
380
public final MethodHandle thrower;
381
private final Function<Object, T> cast;
382
protected MethodHandle filter;
383
private int fakeIdentityCount;
384
385
private TestCase(Class<T> rtype, Function<Object, T> cast,
386
ThrowMode throwMode, Throwable thrown)
387
throws NoSuchMethodException, IllegalAccessException {
388
this.cast = cast;
389
filter = MethodHandles.lookup().findVirtual(
390
Function.class,
391
"apply",
392
MethodType.methodType(Object.class, Object.class))
393
.bindTo(cast);
394
this.rtype = rtype;
395
this.throwMode = throwMode;
396
this.throwableClass = thrown.getClass();
397
switch (throwMode) {
398
case NOTHING:
399
this.thrown = null;
400
break;
401
case ADAPTER:
402
case UNCAUGHT:
403
this.thrown = new Error("do not catch this");
404
break;
405
default:
406
this.thrown = thrown;
407
}
408
409
MethodHandle throwOrReturn = THROW_OR_RETURN;
410
if (throwMode == ThrowMode.ADAPTER) {
411
MethodHandle fakeIdentity = FAKE_IDENTITY.bindTo(this);
412
for (int i = 0; i < 10; ++i) {
413
throwOrReturn = MethodHandles.filterReturnValue(
414
throwOrReturn, fakeIdentity);
415
}
416
}
417
thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
418
}
419
420
private static Void noop(Object x) {
421
return null;
422
}
423
424
private static <T2> PartialConstructor create(
425
Class<T2> rtype, Function<Object, T2> cast) {
426
return (t, u) -> () -> {
427
try {
428
return new TestCase<>(rtype, cast, t, u);
429
} catch (NoSuchMethodException | IllegalAccessException e) {
430
throw new Error(e);
431
}
432
};
433
}
434
435
private static <T extends Throwable>
436
Object throwOrReturn(Object normal, T exception) throws T {
437
if (exception != null) {
438
Helper.called("throwOrReturn/throw", normal, exception);
439
throw exception;
440
}
441
Helper.called("throwOrReturn/normal", normal, exception);
442
return normal;
443
}
444
445
private static <T extends Throwable> Object catcher(Object o) {
446
Helper.called("catcher", o);
447
return o;
448
}
449
450
public MethodHandle filter(MethodHandle target) {
451
return MethodHandles.filterReturnValue(target, filter);
452
}
453
454
public MethodHandle getCatcher(List<Class<?>> classes) {
455
return MethodHandles.filterReturnValue(Helper.AS_LIST.asType(
456
MethodType.methodType(Object.class, classes)),
457
CATCHER
458
);
459
}
460
461
@Override
462
public String toString() {
463
return "TestCase{" +
464
"rtype=" + rtype +
465
", throwMode=" + throwMode +
466
", throwableClass=" + throwableClass +
467
'}';
468
}
469
470
public String callName() {
471
return "throwOrReturn/" +
472
(throwMode == ThrowMode.NOTHING
473
? "normal"
474
: "throw");
475
}
476
477
public void assertReturn(Object returned, Object arg0, Object arg1,
478
int catchDrops, Object... args) {
479
int lag = 0;
480
if (throwMode == ThrowMode.CAUGHT) {
481
lag = 1;
482
}
483
Helper.assertCalled(lag, callName(), arg0, arg1);
484
485
if (throwMode == ThrowMode.NOTHING) {
486
assertEQ(cast.apply(arg0), returned);
487
} else if (throwMode == ThrowMode.CAUGHT) {
488
List<Object> catchArgs = new ArrayList<>(Arrays.asList(args));
489
// catcher receives an initial subsequence of target arguments:
490
catchArgs.subList(args.length - catchDrops, args.length).clear();
491
// catcher also receives the exception, prepended:
492
catchArgs.add(0, thrown);
493
Helper.assertCalled("catcher", catchArgs);
494
assertEQ(cast.apply(catchArgs), returned);
495
}
496
Asserts.assertEQ(0, fakeIdentityCount);
497
}
498
499
private void assertEQ(T t, Object returned) {
500
if (rtype.isArray()) {
501
Asserts.assertEQ(t.getClass(), returned.getClass());
502
int n = Array.getLength(t);
503
Asserts.assertEQ(n, Array.getLength(returned));
504
for (int i = 0; i < n; ++i) {
505
Asserts.assertEQ(Array.get(t, i), Array.get(returned, i));
506
}
507
} else {
508
Asserts.assertEQ(t, returned);
509
}
510
}
511
512
private Object fakeIdentity(Object x) {
513
System.out.println("should throw through this!");
514
++fakeIdentityCount;
515
return x;
516
}
517
518
public void assertCatch(Throwable ex) {
519
try {
520
Asserts.assertSame(thrown, ex,
521
"must get the out-of-band exception");
522
} catch (Throwable t) {
523
ex.printStackTrace();
524
}
525
}
526
527
public interface PartialConstructor
528
extends BiFunction<ThrowMode, Throwable, Supplier<TestCase>> {
529
}
530
}
531
532