Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java
41154 views
1
/*
2
* Copyright (c) 2013, 2018, 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
24
/**
25
* @test
26
* @bug 8025260 8016839 8046171
27
* @summary Ensure that correct exceptions are thrown, not NullPointerException
28
* @modules java.base/jdk.internal.org.objectweb.asm
29
* @library / .
30
*
31
* @build p.*
32
* @run main/othervm compiler.jsr292.methodHandleExceptions.TestAMEnotNPE
33
* @run main/othervm -Xint compiler.jsr292.methodHandleExceptions.TestAMEnotNPE
34
* @run main/othervm -Xcomp compiler.jsr292.methodHandleExceptions.TestAMEnotNPE
35
*/
36
37
// Since this test was written the specification for interface method selection has been
38
// revised (JEP 181 - Nestmates) so that private methods are never selected, as they never
39
// override any inherited method. So where a private method was previously selected
40
// and then resulted in IllegalAccessError, the private method is skipped and the invocation
41
// will either succeed or fail based on what other implementations are found in the inheritance
42
// hierarchy. This is explained for each test below.
43
44
package compiler.jsr292.methodHandleExceptions;
45
46
import p.Dok;
47
import jdk.internal.org.objectweb.asm.ClassWriter;
48
import jdk.internal.org.objectweb.asm.Handle;
49
import jdk.internal.org.objectweb.asm.MethodVisitor;
50
import jdk.internal.org.objectweb.asm.Opcodes;
51
52
import java.lang.reflect.InvocationTargetException;
53
import java.lang.reflect.Method;
54
import java.util.ArrayList;
55
import java.util.List;
56
57
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;
58
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
59
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
60
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
61
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
62
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
63
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
64
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
65
import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
66
import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
67
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
68
import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;
69
70
public class TestAMEnotNPE {
71
72
static boolean writeJarFiles = false;
73
static boolean readJarFiles = false;
74
75
/**
76
* Optional command line parameter (any case-insensitive prefix of)
77
* "writejarfiles" or "readjarfiles".
78
*
79
* "Writejarfiles" creates a jar file for each different set of tested classes.
80
* "Readjarfiles" causes the classloader to use the copies of the classes
81
* found in the corresponding jar files.
82
*
83
* Jarfilenames look something like pD_ext_pF (p.D extends p.F)
84
* and qD_m_pp_imp_pI (q.D with package-private m implements p.I)
85
*
86
*/
87
public static void main(String args[]) throws Throwable {
88
ArrayList<Throwable> lt = new ArrayList<Throwable>();
89
90
if (args.length > 0) {
91
String a0 = args[0].toLowerCase();
92
if (a0.length() > 0) {
93
writeJarFiles = ("writejarfiles").startsWith(a0);
94
readJarFiles = ("readjarfiles").startsWith(a0);
95
}
96
if (!(writeJarFiles || readJarFiles)) {
97
throw new Error("Command line parameter (if any) should be prefix of writeJarFiles or readJarFiles");
98
}
99
}
100
101
System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL");
102
System.out.println(" - should invoke p.F.m as private p.D.m is skipped for selection");
103
tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"),
104
"p.D extends p.F (p.F implements p.I, FINAL public m), private m",
105
null /* should succeed */, "pD_ext_pF");
106
System.out.println();
107
108
System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.E");
109
System.out.println(" - should invoke p.E.m as private p.D.m is skipped for selection");
110
tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/E"),
111
"p.D extends p.E (p.E implements p.I, public m), private m",
112
null /* should succeed */, "pD_ext_pE");
113
114
System.out.println("TRYING p.D.m ABSTRACT interface-invoked as p.I.m");
115
tryAndCheckThrown(lt, bytesForD(),
116
"D extends abstract C, no m",
117
AbstractMethodError.class, "pD_ext_pC");
118
119
System.out.println("TRYING q.D.m PACKAGE interface-invoked as p.I.m");
120
tryAndCheckThrown(lt, "q.D", bytesForDsomeAccess("q/D", 0),
121
"q.D implements p.I, protected m",
122
IllegalAccessError.class, "qD_m_pp_imp_pI");
123
124
// Note jar file name is used in the plural-arg case.
125
System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m");
126
System.out.println(" - should invoke p.I.m as private p.D.m is skipped for selection");
127
tryAndCheckThrown(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
128
"p.D implements p.I, private m",
129
null /* should succeed */, "pD_m_pri_imp_pI");
130
131
// Plural-arg test.
132
System.out.println("TRYING p.D.m PRIVATE MANY ARG interface-invoked as p.I.m");
133
System.out.println(" - should invoke p.I.m as private p.D.m is skipped for selection");
134
tryAndCheckThrownMany(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
135
"p.D implements p.I, private m", null /* should succeed */);
136
137
if (lt.size() > 0) {
138
System.out.flush();
139
Thread.sleep(250); // This de-interleaves output and error in Netbeans, sigh.
140
for (Throwable th : lt)
141
System.err.println(th);
142
throw new Error("Test failed, there were " + lt.size() + " failures listed above");
143
} else {
144
System.out.println("ALL PASS, HOORAY!");
145
}
146
}
147
148
/**
149
* The bytes for D, a NOT abstract class extending abstract class C without
150
* supplying an implementation for abstract method m. There is a default
151
* method in the interface I, but it should lose to the abstract class.
152
*
153
* @return
154
* @throws Exception
155
*/
156
public static byte[] bytesForD() throws Exception {
157
158
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
159
| ClassWriter.COMPUTE_MAXS);
160
MethodVisitor mv;
161
162
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/D", null, "p/C", null);
163
164
{
165
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
166
mv.visitCode();
167
mv.visitVarInsn(ALOAD, 0);
168
mv.visitMethodInsn(INVOKESPECIAL, "p/C", "<init>", "()V");
169
mv.visitInsn(RETURN);
170
mv.visitMaxs(0, 0);
171
mv.visitEnd();
172
}
173
cw.visitEnd();
174
175
return cw.toByteArray();
176
}
177
178
/**
179
* The bytes for D, implements I, does not extend C, declares m()I with
180
* access method_acc.
181
*
182
* @param d_name Name of class defined
183
* @param method_acc Accessibility of that class's method m.
184
* @return
185
* @throws Exception
186
*/
187
public static byte[] bytesForDsomeAccess(String d_name, int method_acc) throws Exception {
188
return bytesForSomeDsubSomethingSomeAccess(d_name, "java/lang/Object", method_acc);
189
}
190
191
/**
192
* The bytes for D implements I, extends some class, declares m()I as
193
* private.
194
*
195
* Invokeinterface of I.m applied to this D should throw IllegalAccessError
196
*
197
* @param sub_what The name of the class that D will extend.
198
* @return
199
* @throws Exception
200
*/
201
public static byte[] bytesForDprivateSubWhat(String sub_what) throws Exception {
202
return bytesForSomeDsubSomethingSomeAccess("p/D", sub_what, ACC_PRIVATE);
203
}
204
205
/**
206
* Returns the bytes for a class with name d_name (presumably "D" in some
207
* package), extending some class with name sub_what, implementing p.I,
208
* and defining two methods m() and m(11args) with access method_acc.
209
*
210
* @param d_name Name of class that is defined
211
* @param sub_what Name of class that it extends
212
* @param method_acc Accessibility of method(s) m in defined class.
213
* @return
214
* @throws Exception
215
*/
216
public static byte[] bytesForSomeDsubSomethingSomeAccess
217
(String d_name, String sub_what, int method_acc)
218
throws Exception {
219
220
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
221
| ClassWriter.COMPUTE_MAXS);
222
MethodVisitor mv;
223
String[] interfaces = {"p/I"};
224
225
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, d_name, null, sub_what, interfaces);
226
{
227
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
228
mv.visitCode();
229
mv.visitVarInsn(ALOAD, 0);
230
mv.visitMethodInsn(INVOKESPECIAL, sub_what, "<init>", "()V");
231
mv.visitInsn(RETURN);
232
mv.visitMaxs(0, 0);
233
mv.visitEnd();
234
}
235
// int m() {return 3;}
236
{
237
mv = cw.visitMethod(method_acc, "m", "()I", null, null);
238
mv.visitCode();
239
mv.visitLdcInsn(new Integer(3));
240
mv.visitInsn(IRETURN);
241
mv.visitMaxs(0, 0);
242
mv.visitEnd();
243
}
244
// int m(11args) {return 3;}
245
{
246
mv = cw.visitMethod(method_acc, "m", "(BCSIJ"
247
+ "Ljava/lang/Object;"
248
+ "Ljava/lang/Object;"
249
+ "Ljava/lang/Object;"
250
+ "Ljava/lang/Object;"
251
+ "Ljava/lang/Object;"
252
+ "Ljava/lang/Object;"
253
+ ")I", null, null);
254
mv.visitCode();
255
mv.visitLdcInsn(new Integer(3));
256
mv.visitInsn(IRETURN);
257
mv.visitMaxs(0, 0);
258
mv.visitEnd();
259
}
260
cw.visitEnd();
261
return cw.toByteArray();
262
}
263
264
/**
265
* The bytecodes for a class p/T defining a methods test() and test(11args)
266
* that contain an invokeExact of a particular methodHandle, I.m.
267
*
268
* Test will be passed values that may imperfectly implement I,
269
* and thus may in turn throw exceptions.
270
*
271
* @return
272
* @throws Exception
273
*/
274
public static byte[] bytesForT() throws Exception {
275
276
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
277
| ClassWriter.COMPUTE_MAXS);
278
MethodVisitor mv;
279
280
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/T", null, "java/lang/Object", null);
281
{
282
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
283
mv.visitCode();
284
mv.visitVarInsn(ALOAD, 0);
285
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
286
mv.visitInsn(RETURN);
287
mv.visitMaxs(0, 0);
288
mv.visitEnd();
289
}
290
// static int test(I)
291
{
292
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;)I", null, null);
293
mv.visitCode();
294
mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "()I"));
295
mv.visitVarInsn(ALOAD, 0);
296
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
297
"invokeExact", "(Lp/I;)I");
298
mv.visitInsn(IRETURN);
299
mv.visitMaxs(0, 0);
300
mv.visitEnd();
301
}
302
// static int test(I,11args)
303
{
304
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", null, null);
305
mv.visitCode();
306
mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "(BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I"));
307
mv.visitVarInsn(ALOAD, 0);
308
mv.visitVarInsn(ILOAD, 1);
309
mv.visitVarInsn(ILOAD, 2);
310
mv.visitVarInsn(ILOAD, 3);
311
mv.visitVarInsn(ILOAD, 4);
312
mv.visitVarInsn(LLOAD, 5);
313
mv.visitVarInsn(ALOAD, 7);
314
mv.visitVarInsn(ALOAD, 8);
315
mv.visitVarInsn(ALOAD, 9);
316
mv.visitVarInsn(ALOAD, 10);
317
mv.visitVarInsn(ALOAD, 11);
318
mv.visitVarInsn(ALOAD, 12);
319
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
320
"invokeExact", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I");
321
mv.visitInsn(IRETURN);
322
mv.visitMaxs(0, 0);
323
mv.visitEnd();
324
}
325
cw.visitEnd();
326
return cw.toByteArray();
327
}
328
329
private static void tryAndCheckThrown(
330
List<Throwable> lt, byte[] dBytes, String what, Class<?> expected, String jar_name)
331
throws Throwable {
332
tryAndCheckThrown(lt, "p.D", dBytes, what, expected, jar_name);
333
}
334
335
private static void tryAndCheckThrown(List<Throwable> lt, String d_name, byte[] dBytes, String what, Class<?> expected, String jar_name)
336
throws Throwable {
337
338
System.out.println("Methodhandle invokeExact I.m() for instance of " + what);
339
ByteClassLoader bcl1 = new ByteClassLoader(jar_name, readJarFiles, writeJarFiles);
340
try {
341
Class<?> d1 = bcl1.loadBytes(d_name, dBytes);
342
Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
343
invokeTest(t1, d1, expected, lt);
344
} finally {
345
// Not necessary for others -- all class files are written in this call.
346
// (unless the VM crashes first).
347
bcl1.close();
348
}
349
350
System.out.println("Reflection invoke I.m() for instance of " + what);
351
ByteClassLoader bcl3 = new ByteClassLoader(jar_name, readJarFiles, false);
352
Class<?> d3 = bcl3.loadBytes(d_name, dBytes);
353
Class<?> t3 = bcl3.loadClass("p.Treflect");
354
invokeTest(t3, d3, expected, lt);
355
356
System.out.println("Bytecode invokeInterface I.m() for instance of " + what);
357
ByteClassLoader bcl2 = new ByteClassLoader(jar_name, readJarFiles, false);
358
Class<?> d2 = bcl2.loadBytes(d_name, dBytes);
359
Class<?> t2 = bcl2.loadClass("p.Tdirect");
360
badGoodBadGood(t2, d2, expected, lt);
361
}
362
363
private static void invokeTest(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
364
throws Throwable {
365
try {
366
Method m = t.getMethod("test", p.I.class);
367
Object o = d.newInstance();
368
Object result = m.invoke(null, o);
369
if (expected != null) {
370
System.out.println("FAIL, Expected " + expected.getName()
371
+ " wrapped in InvocationTargetException, but nothing was thrown");
372
lt.add(new Error("Exception " + expected.getName() + " was not thrown"));
373
} else {
374
System.out.println("PASS, saw expected return.");
375
}
376
} catch (InvocationTargetException e) {
377
Throwable th = e.getCause();
378
th.printStackTrace(System.out);
379
if (expected != null) {
380
if (expected.isInstance(th)) {
381
System.out.println("PASS, saw expected exception (" + expected.getName() + ").");
382
} else {
383
System.out.println("FAIL, Expected " + expected.getName()
384
+ " wrapped in InvocationTargetException, saw " + th);
385
lt.add(th);
386
}
387
} else {
388
System.out.println("FAIL, expected no exception, saw " + th);
389
lt.add(th);
390
}
391
}
392
System.out.println();
393
}
394
395
/* Many-arg versions of above */
396
private static void tryAndCheckThrownMany(List<Throwable> lt, byte[] dBytes, String what, Class<?> expected)
397
throws Throwable {
398
399
System.out.println("Methodhandle invokeExact I.m(11params) for instance of " + what);
400
ByteClassLoader bcl1 = new ByteClassLoader("p.D", readJarFiles, false);
401
try {
402
Class<?> d1 = bcl1.loadBytes("p.D", dBytes);
403
Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
404
invokeTestMany(t1, d1, expected, lt);
405
} finally {
406
bcl1.close(); // Not necessary for others -- all class files are written in this call.
407
}
408
409
{
410
System.out.println("Bytecode invokeInterface I.m(11params) for instance of " + what);
411
ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
412
Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
413
Class<?> t2 = bcl2.loadClass("p.Tdirect");
414
badGoodBadGoodMany(t2, d2, expected, lt);
415
416
}
417
{
418
System.out.println("Reflection invokeInterface I.m(11params) for instance of " + what);
419
ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
420
Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
421
Class<?> t2 = bcl2.loadClass("p.Treflect");
422
invokeTestMany(t2, d2, expected, lt);
423
}
424
}
425
426
private static void invokeTestMany(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
427
throws Throwable {
428
try {
429
Method m = t.getMethod("test", p.I.class,
430
Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE,
431
Object.class, Object.class, Object.class,
432
Object.class, Object.class, Object.class);
433
Object o = d.newInstance();
434
Byte b = 1;
435
Character c = 2;
436
Short s = 3;
437
Integer i = 4;
438
Long j = 5L;
439
Object o1 = b;
440
Object o2 = c;
441
Object o3 = s;
442
Object o4 = i;
443
Object o5 = j;
444
Object o6 = "6";
445
446
Object result = m.invoke(null, o, b, c, s, i, j,
447
o1, o2, o3, o4, o5, o6);
448
if (expected != null) {
449
System.out.println("FAIL, Expected " + expected.getName()
450
+ " wrapped in InvocationTargetException, but nothing was thrown");
451
lt.add(new Error("Exception " + expected.getName()
452
+ " was not thrown"));
453
} else {
454
System.out.println("PASS, saw expected return.");
455
}
456
} catch (InvocationTargetException e) {
457
Throwable th = e.getCause();
458
th.printStackTrace(System.out);
459
if (expected != null) {
460
if (expected.isInstance(th)) {
461
System.out.println("PASS, saw expected exception ("
462
+ expected.getName() + ").");
463
} else {
464
System.out.println("FAIL, Expected " + expected.getName()
465
+ " wrapped in InvocationTargetException, saw " + th);
466
lt.add(th);
467
}
468
} else {
469
System.out.println("FAIL, expected no exception, saw " + th);
470
lt.add(th);
471
}
472
}
473
System.out.println();
474
}
475
476
/**
477
* This tests a peculiar idiom for tickling the bug on older VMs that lack
478
* methodhandles. The bug (if not fixed) acts in the following way:
479
*
480
* When a broken receiver is passed to the first execution of an invokeinterface
481
* bytecode, the illegal access is detected before the effects of resolution are
482
* cached for later use, and so repeated calls with a broken receiver will always
483
* throw the correct error.
484
*
485
* If, however, a good receiver is passed to the invokeinterface, the effects of
486
* resolution will be successfully cached. A subsequent execution with a broken
487
* receiver will reuse the cached information, skip the detailed resolution work,
488
* and instead encounter a null pointer. By convention, that is the encoding for a
489
* missing abstract method, and an AbstractMethodError is thrown -- not the expected
490
* IllegalAccessError.
491
*
492
* @param t2 Test invocation class
493
* @param d2 Test receiver class
494
* @param expected expected exception type
495
* @param lt list of unexpected throwables seen
496
*/
497
private static void badGoodBadGood(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
498
throws Throwable {
499
System.out.println(" Error input 1st time");
500
invokeTest(t2, d2, expected, lt);
501
System.out.println(" Good input (instance of Dok)");
502
invokeTest(t2, Dok.class, null, lt);
503
System.out.println(" Error input 2nd time");
504
invokeTest(t2, d2, expected, lt);
505
System.out.println(" Good input (instance of Dok)");
506
invokeTest(t2, Dok.class, null, lt);
507
}
508
509
private static void badGoodBadGoodMany(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
510
throws Throwable {
511
System.out.println(" Error input 1st time");
512
invokeTestMany(t2, d2, expected, lt);
513
System.out.println(" Good input (instance of Dok)");
514
invokeTestMany(t2, Dok.class, null, lt);
515
System.out.println(" Error input 2nd time");
516
invokeTestMany(t2, d2, expected, lt);
517
System.out.println(" Good input (instance of Dok)");
518
invokeTestMany(t2, Dok.class, null, lt);
519
}
520
}
521
522