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/RevealDirectTest.java
47216 views
1
/*
2
* Copyright (c) 2013, 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
* @summary verify Lookup.revealDirect on a variety of input handles
27
* @compile -XDignore.symbol.file RevealDirectTest.java
28
* @run junit/othervm -ea -esa test.java.lang.invoke.RevealDirectTest
29
*
30
* @test
31
* @summary verify Lookup.revealDirect on a variety of input handles, with security manager
32
* @run main/othervm/policy=jtreg.security.policy/secure=java.lang.SecurityManager -ea -esa test.java.lang.invoke.RevealDirectTest
33
*/
34
35
/* To run manually:
36
* $ $JAVA8X_HOME/bin/javac -cp $JUNIT4_JAR -d ../../../.. -XDignore.symbol.file RevealDirectTest.java
37
* $ $JAVA8X_HOME/bin/java -cp $JUNIT4_JAR:../../../.. -ea -esa org.junit.runner.JUnitCore test.java.lang.invoke.RevealDirectTest
38
* $ $JAVA8X_HOME/bin/java -cp $JUNIT4_JAR:../../../.. -ea -esa -Djava.security.manager test.java.lang.invoke.RevealDirectTest
39
*/
40
41
package test.java.lang.invoke;
42
43
import java.lang.reflect.*;
44
import java.lang.invoke.*;
45
import static java.lang.invoke.MethodHandles.*;
46
import static java.lang.invoke.MethodType.*;
47
import static java.lang.invoke.MethodHandleInfo.*;
48
import java.util.*;
49
import static org.junit.Assert.*;
50
import org.junit.*;
51
52
public class RevealDirectTest {
53
public static void main(String... av) throws Throwable {
54
// Run the @Test methods explicitly, in case we don't want to use the JUnitCore driver.
55
// This appears to be necessary when running with a security manager.
56
Throwable fail = null;
57
for (Method test : RevealDirectTest.class.getDeclaredMethods()) {
58
if (!test.isAnnotationPresent(Test.class)) continue;
59
try {
60
test.invoke(new RevealDirectTest());
61
} catch (Throwable ex) {
62
if (ex instanceof InvocationTargetException)
63
ex = ex.getCause();
64
if (fail == null) fail = ex;
65
System.out.println("Testcase: "+test.getName()
66
+"("+test.getDeclaringClass().getName()
67
+"):\tCaused an ERROR");
68
System.out.println(ex);
69
ex.printStackTrace(System.out);
70
}
71
}
72
if (fail != null) throw fail;
73
}
74
75
public interface SimpleSuperInterface {
76
public abstract int getInt();
77
public static void printAll(String... args) {
78
System.out.println(Arrays.toString(args));
79
}
80
public int NICE_CONSTANT = 42;
81
}
82
public interface SimpleInterface extends SimpleSuperInterface {
83
default float getFloat() { return getInt(); }
84
public static void printAll(String[] args) {
85
System.out.println(Arrays.toString(args));
86
}
87
}
88
public static class Simple implements SimpleInterface, Cloneable {
89
public int intField;
90
public final int finalField;
91
private static String stringField;
92
public int getInt() { return NICE_CONSTANT; }
93
private static Number getNum() { return 804; }
94
public Simple clone() {
95
try {
96
return (Simple) super.clone();
97
} catch (CloneNotSupportedException ex) {
98
throw new RuntimeException(ex);
99
}
100
}
101
Simple() { finalField = -NICE_CONSTANT; }
102
private static Lookup localLookup() { return lookup(); }
103
private static List<Member> members() { return getMembers(lookup().lookupClass()); };
104
}
105
static class Nestmate {
106
private static Lookup localLookup() { return lookup(); }
107
}
108
109
static boolean VERBOSE = false;
110
111
@Test public void testSimple() throws Throwable {
112
if (VERBOSE) System.out.println("@Test testSimple");
113
testOnMembers("testSimple", Simple.members(), Simple.localLookup());
114
}
115
@Test public void testPublicLookup() throws Throwable {
116
if (VERBOSE) System.out.println("@Test testPublicLookup");
117
List<Member> mems = publicOnly(Simple.members());
118
Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
119
testOnMembers("testPublicLookup/1", mems, pubLookup);
120
// reveal using publicLookup:
121
testOnMembers("testPublicLookup/2", mems, privLookup, pubLookup);
122
// lookup using publicLookup, but reveal using private:
123
testOnMembers("testPublicLookup/3", mems, pubLookup, privLookup);
124
}
125
@Test public void testPublicLookupNegative() throws Throwable {
126
if (VERBOSE) System.out.println("@Test testPublicLookupNegative");
127
List<Member> mems = nonPublicOnly(Simple.members());
128
Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
129
testOnMembersNoLookup("testPublicLookupNegative/1", mems, pubLookup);
130
testOnMembersNoReveal("testPublicLookupNegative/2", mems, privLookup, pubLookup);
131
testOnMembersNoReflect("testPublicLookupNegative/3", mems, privLookup, pubLookup);
132
}
133
@Test public void testJavaLangClass() throws Throwable {
134
if (VERBOSE) System.out.println("@Test testJavaLangClass");
135
List<Member> mems = callerSensitive(false, publicOnly(getMembers(Class.class)));
136
mems = limit(20, mems);
137
testOnMembers("testJavaLangClass", mems, Simple.localLookup());
138
}
139
@Test public void testCallerSensitive() throws Throwable {
140
if (VERBOSE) System.out.println("@Test testCallerSensitive");
141
List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
142
getMembers(Method.class, "invoke"),
143
getMembers(Field.class, "get", "set", "getLong"),
144
getMembers(Class.class));
145
mems = callerSensitive(true, publicOnly(mems));
146
mems = limit(10, mems);
147
testOnMembers("testCallerSensitive", mems, Simple.localLookup());
148
}
149
@Test public void testCallerSensitiveNegative() throws Throwable {
150
if (VERBOSE) System.out.println("@Test testCallerSensitiveNegative");
151
List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
152
getMembers(Class.class, "forName"),
153
getMembers(Method.class, "invoke"));
154
mems = callerSensitive(true, publicOnly(mems));
155
// CS methods cannot be looked up with publicLookup
156
testOnMembersNoLookup("testCallerSensitiveNegative/1", mems, publicLookup());
157
// CS methods have to be revealed with a matching lookupClass
158
testOnMembersNoReveal("testCallerSensitiveNegative/2", mems, Simple.localLookup(), publicLookup());
159
testOnMembersNoReveal("testCallerSensitiveNegative/3", mems, Simple.localLookup(), Nestmate.localLookup());
160
}
161
@Test public void testMethodHandleNatives() throws Throwable {
162
if (VERBOSE) System.out.println("@Test testMethodHandleNatives");
163
List<Member> mems = getMembers(MethodHandle.class, "invoke", "invokeExact");
164
testOnMembers("testMethodHandleNatives", mems, Simple.localLookup());
165
}
166
@Test public void testMethodHandleInvokes() throws Throwable {
167
if (VERBOSE) System.out.println("@Test testMethodHandleInvokes");
168
List<MethodType> types = new ArrayList<>();
169
Class<?>[] someParamTypes = { void.class, int.class, Object.class, Object[].class };
170
for (Class<?> rt : someParamTypes) {
171
for (Class<?> p0 : someParamTypes) {
172
if (p0 == void.class) { types.add(methodType(rt)); continue; }
173
for (Class<?> p1 : someParamTypes) {
174
if (p1 == void.class) { types.add(methodType(rt, p0)); continue; }
175
for (Class<?> p2 : someParamTypes) {
176
if (p2 == void.class) { types.add(methodType(rt, p0, p1)); continue; }
177
types.add(methodType(rt, p0, p1, p2));
178
}
179
}
180
}
181
}
182
List<Member> mems = union(getPolyMembers(MethodHandle.class, "invoke", types),
183
getPolyMembers(MethodHandle.class, "invokeExact", types));
184
testOnMembers("testMethodHandleInvokes/1", mems, Simple.localLookup());
185
testOnMembers("testMethodHandleInvokes/2", mems, publicLookup());
186
}
187
188
static List<Member> getPolyMembers(Class<?> cls, String name, List<MethodType> types) {
189
assert(cls == MethodHandle.class);
190
ArrayList<Member> mems = new ArrayList<>();
191
for (MethodType type : types) {
192
mems.add(new SignaturePolymorphicMethod(name, type));
193
}
194
return mems;
195
}
196
static List<Member> getMembers(Class<?> cls) {
197
return getMembers(cls, (String[]) null);
198
}
199
static List<Member> getMembers(Class<?> cls, String... onlyNames) {
200
List<String> names = (onlyNames == null || onlyNames.length == 0 ? null : Arrays.asList(onlyNames));
201
ArrayList<Member> res = new ArrayList<>();
202
for (Class<?> sup : getSupers(cls)) {
203
res.addAll(getDeclaredMembers(sup, "getDeclaredFields"));
204
res.addAll(getDeclaredMembers(sup, "getDeclaredMethods"));
205
res.addAll(getDeclaredMembers(sup, "getDeclaredConstructors"));
206
}
207
res = new ArrayList<>(new LinkedHashSet<>(res));
208
for (int i = 0; i < res.size(); i++) {
209
Member mem = res.get(i);
210
if (!canBeReached(mem, cls) ||
211
res.indexOf(mem) != i ||
212
mem.isSynthetic() ||
213
(names != null && !names.contains(mem.getName()))
214
) {
215
res.remove(i--);
216
}
217
}
218
return res;
219
}
220
static List<Class<?>> getSupers(Class<?> cls) {
221
ArrayList<Class<?>> res = new ArrayList<>();
222
ArrayList<Class<?>> intfs = new ArrayList<>();
223
for (Class<?> sup = cls; sup != null; sup = sup.getSuperclass()) {
224
res.add(sup);
225
for (Class<?> intf : cls.getInterfaces()) {
226
if (!intfs.contains(intf))
227
intfs.add(intf);
228
}
229
}
230
for (int i = 0; i < intfs.size(); i++) {
231
for (Class<?> intf : intfs.get(i).getInterfaces()) {
232
if (!intfs.contains(intf))
233
intfs.add(intf);
234
}
235
}
236
res.addAll(intfs);
237
//System.out.println("getSupers => "+res);
238
return res;
239
}
240
static boolean hasSM() {
241
return (System.getSecurityManager() != null);
242
}
243
static List<Member> getDeclaredMembers(Class<?> cls, String accessor) {
244
Member[] mems = {};
245
Method getter = getMethod(Class.class, accessor);
246
if (hasSM()) {
247
try {
248
mems = (Member[]) invokeMethod(getter, cls);
249
} catch (SecurityException ex) {
250
//if (VERBOSE) ex.printStackTrace();
251
accessor = accessor.replace("Declared", "");
252
getter = getMethod(Class.class, accessor);
253
if (VERBOSE) System.out.println("replaced accessor: "+getter);
254
}
255
}
256
if (mems.length == 0) {
257
try {
258
mems = (Member[]) invokeMethod(getter, cls);
259
} catch (SecurityException ex) {
260
ex.printStackTrace();
261
}
262
}
263
if (VERBOSE) System.out.println(accessor+" "+cls.getName()+" => "+mems.length+" members");
264
return Arrays.asList(mems);
265
}
266
static Method getMethod(Class<?> cls, String name) {
267
try {
268
return cls.getMethod(name);
269
} catch (ReflectiveOperationException ex) {
270
throw new AssertionError(ex);
271
}
272
}
273
static Object invokeMethod(Method m, Object recv, Object... args) {
274
try {
275
return m.invoke(recv, args);
276
} catch (InvocationTargetException ex) {
277
Throwable ex2 = ex.getCause();
278
if (ex2 instanceof RuntimeException) throw (RuntimeException) ex2;
279
if (ex2 instanceof Error) throw (Error) ex2;
280
throw new AssertionError(ex);
281
} catch (ReflectiveOperationException ex) {
282
throw new AssertionError(ex);
283
}
284
}
285
286
static List<Member> limit(int len, List<Member> mems) {
287
if (mems.size() <= len) return mems;
288
return mems.subList(0, len);
289
}
290
@SafeVarargs
291
static List<Member> union(List<Member> mems, List<Member>... mem2s) {
292
for (List<Member> mem2 : mem2s) {
293
for (Member m : mem2) {
294
if (!mems.contains(m))
295
mems.add(m);
296
}
297
}
298
return mems;
299
}
300
static List<Member> callerSensitive(boolean cond, List<Member> members) {
301
for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
302
Member mem = i.next();
303
if (isCallerSensitive(mem) != cond)
304
i.remove();
305
}
306
if (members.isEmpty()) throw new AssertionError("trivial result");
307
return members;
308
}
309
static boolean isCallerSensitive(Member mem) {
310
if (!(mem instanceof AnnotatedElement)) return false;
311
AnnotatedElement ae = (AnnotatedElement) mem;
312
if (CS_CLASS != null)
313
return ae.isAnnotationPresent(sun.reflect.CallerSensitive.class);
314
for (java.lang.annotation.Annotation a : ae.getDeclaredAnnotations()) {
315
if (a.toString().contains(".CallerSensitive"))
316
return true;
317
}
318
return false;
319
}
320
static final Class<?> CS_CLASS;
321
static {
322
Class<?> c = null;
323
try {
324
c = sun.reflect.CallerSensitive.class;
325
} catch (SecurityException | LinkageError ex) {
326
}
327
CS_CLASS = c;
328
}
329
static List<Member> publicOnly(List<Member> members) {
330
return removeMods(members, Modifier.PUBLIC, 0);
331
}
332
static List<Member> nonPublicOnly(List<Member> members) {
333
return removeMods(members, Modifier.PUBLIC, -1);
334
}
335
static List<Member> removeMods(List<Member> members, int mask, int bits) {
336
int publicMods = (mask & Modifier.PUBLIC);
337
members = new ArrayList<>(members);
338
for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
339
Member mem = i.next();
340
int mods = mem.getModifiers();
341
if ((publicMods & mods) != 0 &&
342
(publicMods & mem.getDeclaringClass().getModifiers()) == 0)
343
mods -= publicMods;
344
if ((mods & mask) == (bits & mask))
345
i.remove();
346
}
347
return members;
348
}
349
350
void testOnMembers(String tname, List<Member> mems, Lookup lookup, Lookup... lookups) throws Throwable {
351
if (VERBOSE) System.out.println("testOnMembers "+mems);
352
Lookup revLookup = (lookups.length > 0) ? lookups[0] : null;
353
if (revLookup == null) revLookup = lookup;
354
Lookup refLookup = (lookups.length > 1) ? lookups[1] : null;
355
if (refLookup == null) refLookup = lookup;
356
assert(lookups.length <= 2);
357
testOnMembersImpl(tname, mems, lookup, revLookup, refLookup, NO_FAIL);
358
}
359
void testOnMembersNoLookup(String tname, List<Member> mems, Lookup lookup) throws Throwable {
360
if (VERBOSE) System.out.println("testOnMembersNoLookup "+mems);
361
testOnMembersImpl(tname, mems, lookup, null, null, FAIL_LOOKUP);
362
}
363
void testOnMembersNoReveal(String tname, List<Member> mems,
364
Lookup lookup, Lookup negLookup) throws Throwable {
365
if (VERBOSE) System.out.println("testOnMembersNoReveal "+mems);
366
testOnMembersImpl(tname, mems, lookup, negLookup, null, FAIL_REVEAL);
367
}
368
void testOnMembersNoReflect(String tname, List<Member> mems,
369
Lookup lookup, Lookup negLookup) throws Throwable {
370
if (VERBOSE) System.out.println("testOnMembersNoReflect "+mems);
371
testOnMembersImpl(tname, mems, lookup, lookup, negLookup, FAIL_REFLECT);
372
}
373
void testOnMembersImpl(String tname, List<Member> mems,
374
Lookup lookup,
375
Lookup revLookup,
376
Lookup refLookup,
377
int failureMode) throws Throwable {
378
Throwable fail = null;
379
int failCount = 0;
380
failureModeCounts = new int[FAIL_MODE_COUNT];
381
long tm0 = System.currentTimeMillis();
382
for (Member mem : mems) {
383
try {
384
testWithMember(mem, lookup, revLookup, refLookup, failureMode);
385
} catch (Throwable ex) {
386
if (fail == null) fail = ex;
387
if (++failCount > 10) { System.out.println("*** FAIL: too many failures"); break; }
388
System.out.println("*** FAIL: "+mem+" => "+ex);
389
if (VERBOSE) ex.printStackTrace(System.out);
390
}
391
}
392
long tm1 = System.currentTimeMillis();
393
System.out.printf("@Test %s executed %s tests in %d ms",
394
tname, testKinds(failureModeCounts), (tm1-tm0)).println();
395
if (fail != null) throw fail;
396
}
397
static String testKinds(int[] modes) {
398
int pos = modes[0], neg = -pos;
399
for (int n : modes) neg += n;
400
if (neg == 0) return pos + " positive";
401
String negs = "";
402
for (int n : modes) negs += "/"+n;
403
negs = negs.replaceFirst("/"+pos+"/", "");
404
negs += " negative";
405
if (pos == 0) return negs;
406
return pos + " positive, " + negs;
407
}
408
static class SignaturePolymorphicMethod implements Member { // non-reflected instance of MH.invoke*
409
final String name;
410
final MethodType type;
411
SignaturePolymorphicMethod(String name, MethodType type) {
412
this.name = name;
413
this.type = type;
414
}
415
public String toString() {
416
String typeStr = type.toString();
417
if (isVarArgs()) typeStr = typeStr.replaceFirst("\\[\\])$", "...)");
418
return (Modifier.toString(getModifiers())
419
+typeStr.substring(0, typeStr.indexOf('('))+" "
420
+getDeclaringClass().getTypeName()+"."
421
+getName()+typeStr.substring(typeStr.indexOf('(')));
422
}
423
public boolean equals(Object x) {
424
return (x instanceof SignaturePolymorphicMethod && equals((SignaturePolymorphicMethod)x));
425
}
426
public boolean equals(SignaturePolymorphicMethod that) {
427
return this.name.equals(that.name) && this.type.equals(that.type);
428
}
429
public int hashCode() {
430
return name.hashCode() * 31 + type.hashCode();
431
}
432
public Class<?> getDeclaringClass() { return MethodHandle.class; }
433
public String getName() { return name; }
434
public MethodType getMethodType() { return type; }
435
public int getModifiers() { return Modifier.PUBLIC | Modifier.FINAL | Modifier.NATIVE | SYNTHETIC; }
436
public boolean isVarArgs() { return Modifier.isTransient(getModifiers()); }
437
public boolean isSynthetic() { return true; }
438
public Class<?> getReturnType() { return type.returnType(); }
439
public Class<?>[] getParameterTypes() { return type.parameterArray(); }
440
static final int SYNTHETIC = 0x00001000;
441
}
442
static class UnreflectResult { // a tuple
443
final MethodHandle mh;
444
final Throwable ex;
445
final byte kind;
446
final Member mem;
447
final int var;
448
UnreflectResult(MethodHandle mh, byte kind, Member mem, int var) {
449
this.mh = mh;
450
this.ex = null;
451
this.kind = kind;
452
this.mem = mem;
453
this.var = var;
454
}
455
UnreflectResult(Throwable ex, byte kind, Member mem, int var) {
456
this.mh = null;
457
this.ex = ex;
458
this.kind = kind;
459
this.mem = mem;
460
this.var = var;
461
}
462
public String toString() {
463
return toInfoString()+"/v"+var;
464
}
465
public String toInfoString() {
466
return String.format("%s %s.%s:%s", MethodHandleInfo.referenceKindToString(kind),
467
mem.getDeclaringClass().getName(), name(mem), type(mem, kind));
468
}
469
static String name(Member mem) {
470
if (mem instanceof Constructor) return "<init>";
471
return mem.getName();
472
}
473
static MethodType type(Member mem, byte kind) {
474
if (mem instanceof Field) {
475
Class<?> type = ((Field)mem).getType();
476
if (kind == REF_putStatic || kind == REF_putField)
477
return methodType(void.class, type);
478
return methodType(type);
479
} else if (mem instanceof SignaturePolymorphicMethod) {
480
return ((SignaturePolymorphicMethod)mem).getMethodType();
481
}
482
Class<?>[] params = ((Executable)mem).getParameterTypes();
483
if (mem instanceof Constructor)
484
return methodType(void.class, params);
485
Class<?> type = ((Method)mem).getReturnType();
486
return methodType(type, params);
487
}
488
}
489
static UnreflectResult unreflectMember(Lookup lookup, Member mem, int variation) {
490
byte[] refKind = {0};
491
try {
492
return unreflectMemberOrThrow(lookup, mem, variation, refKind);
493
} catch (ReflectiveOperationException|SecurityException ex) {
494
return new UnreflectResult(ex, refKind[0], mem, variation);
495
}
496
}
497
static UnreflectResult unreflectMemberOrThrow(Lookup lookup, Member mem, int variation,
498
byte[] refKind) throws ReflectiveOperationException {
499
Class<?> cls = lookup.lookupClass();
500
Class<?> defc = mem.getDeclaringClass();
501
String name = mem.getName();
502
int mods = mem.getModifiers();
503
boolean isStatic = Modifier.isStatic(mods);
504
MethodHandle mh = null;
505
byte kind = 0;
506
if (mem instanceof Method) {
507
Method m = (Method) mem;
508
MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
509
boolean canBeSpecial = (!isStatic &&
510
(lookup.lookupModes() & Modifier.PRIVATE) != 0 &&
511
defc.isAssignableFrom(cls) &&
512
(!defc.isInterface() || Arrays.asList(cls.getInterfaces()).contains(defc)));
513
if (variation >= 2)
514
kind = REF_invokeSpecial;
515
else if (isStatic)
516
kind = REF_invokeStatic;
517
else if (defc.isInterface())
518
kind = REF_invokeInterface;
519
else
520
kind = REF_invokeVirtual;
521
refKind[0] = kind;
522
switch (variation) {
523
case 0:
524
mh = lookup.unreflect(m);
525
break;
526
case 1:
527
if (defc == MethodHandle.class &&
528
!isStatic &&
529
m.isVarArgs() &&
530
Modifier.isFinal(mods) &&
531
Modifier.isNative(mods)) {
532
break;
533
}
534
if (isStatic)
535
mh = lookup.findStatic(defc, name, type);
536
else
537
mh = lookup.findVirtual(defc, name, type);
538
break;
539
case 2:
540
if (!canBeSpecial)
541
break;
542
mh = lookup.unreflectSpecial(m, lookup.lookupClass());
543
break;
544
case 3:
545
if (!canBeSpecial)
546
break;
547
mh = lookup.findSpecial(defc, name, type, lookup.lookupClass());
548
break;
549
}
550
} else if (mem instanceof SignaturePolymorphicMethod) {
551
SignaturePolymorphicMethod m = (SignaturePolymorphicMethod) mem;
552
MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
553
kind = REF_invokeVirtual;
554
refKind[0] = kind;
555
switch (variation) {
556
case 0:
557
mh = lookup.findVirtual(defc, name, type);
558
break;
559
}
560
} else if (mem instanceof Constructor) {
561
name = "<init>"; // not used
562
Constructor<?> m = (Constructor<?>) mem;
563
MethodType type = methodType(void.class, m.getParameterTypes());
564
kind = REF_newInvokeSpecial;
565
refKind[0] = kind;
566
switch (variation) {
567
case 0:
568
mh = lookup.unreflectConstructor(m);
569
break;
570
case 1:
571
mh = lookup.findConstructor(defc, type);
572
break;
573
}
574
} else if (mem instanceof Field) {
575
Field m = (Field) mem;
576
Class<?> type = m.getType();
577
boolean canHaveSetter = !Modifier.isFinal(mods);
578
if (variation >= 2)
579
kind = (byte)(isStatic ? REF_putStatic : REF_putField);
580
else
581
kind = (byte)(isStatic ? REF_getStatic : REF_getField);
582
refKind[0] = kind;
583
switch (variation) {
584
case 0:
585
mh = lookup.unreflectGetter(m);
586
break;
587
case 1:
588
if (isStatic)
589
mh = lookup.findStaticGetter(defc, name, type);
590
else
591
mh = lookup.findGetter(defc, name, type);
592
break;
593
case 3:
594
if (!canHaveSetter)
595
break;
596
mh = lookup.unreflectSetter(m);
597
break;
598
case 2:
599
if (!canHaveSetter)
600
break;
601
if (isStatic)
602
mh = lookup.findStaticSetter(defc, name, type);
603
else
604
mh = lookup.findSetter(defc, name, type);
605
break;
606
}
607
} else {
608
throw new IllegalArgumentException(String.valueOf(mem));
609
}
610
if (mh == null)
611
// ran out of valid variations; return null to caller
612
return null;
613
return new UnreflectResult(mh, kind, mem, variation);
614
}
615
static boolean canBeReached(Member mem, Class<?> cls) {
616
Class<?> defc = mem.getDeclaringClass();
617
String name = mem.getName();
618
int mods = mem.getModifiers();
619
if (mem instanceof Constructor) {
620
name = "<init>"; // according to 292 spec.
621
}
622
if (defc == cls)
623
return true;
624
if (name.startsWith("<"))
625
return false; // only my own constructors
626
if (Modifier.isPrivate(mods))
627
return false; // only my own constructors
628
if (defc.getPackage() == cls.getPackage())
629
return true; // package access or greater OK
630
if (Modifier.isPublic(mods))
631
return true; // publics always OK
632
if (Modifier.isProtected(mods) && defc.isAssignableFrom(cls))
633
return true; // protected OK
634
return false;
635
}
636
static boolean consistent(UnreflectResult res, MethodHandleInfo info) {
637
assert(res.mh != null);
638
assertEquals(res.kind, info.getReferenceKind());
639
assertEquals(res.mem.getModifiers(), info.getModifiers());
640
assertEquals(res.mem.getDeclaringClass(), info.getDeclaringClass());
641
String expectName = res.mem.getName();
642
if (res.kind == REF_newInvokeSpecial)
643
expectName = "<init>";
644
assertEquals(expectName, info.getName());
645
MethodType expectType = res.mh.type();
646
if ((res.kind & 1) == (REF_getField & 1))
647
expectType = expectType.dropParameterTypes(0, 1);
648
if (res.kind == REF_newInvokeSpecial)
649
expectType = expectType.changeReturnType(void.class);
650
assertEquals(expectType, info.getMethodType());
651
assertEquals(res.mh.isVarargsCollector(), isVarArgs(info));
652
assertEquals(res.toInfoString(), info.toString());
653
assertEquals(res.toInfoString(), MethodHandleInfo.toString(info.getReferenceKind(), info.getDeclaringClass(), info.getName(), info.getMethodType()));
654
return true;
655
}
656
static boolean isVarArgs(MethodHandleInfo info) {
657
return info.isVarArgs();
658
}
659
static boolean consistent(Member mem, Member mem2) {
660
assertEquals(mem, mem2);
661
return true;
662
}
663
static boolean consistent(MethodHandleInfo info, MethodHandleInfo info2) {
664
assertEquals(info.getReferenceKind(), info2.getReferenceKind());
665
assertEquals(info.getModifiers(), info2.getModifiers());
666
assertEquals(info.getDeclaringClass(), info2.getDeclaringClass());
667
assertEquals(info.getName(), info2.getName());
668
assertEquals(info.getMethodType(), info2.getMethodType());
669
assertEquals(isVarArgs(info), isVarArgs(info));
670
return true;
671
}
672
static boolean consistent(MethodHandle mh, MethodHandle mh2) {
673
assertEquals(mh.type(), mh2.type());
674
assertEquals(mh.isVarargsCollector(), mh2.isVarargsCollector());
675
return true;
676
}
677
int[] failureModeCounts;
678
static final int NO_FAIL=0, FAIL_LOOKUP=1, FAIL_REVEAL=2, FAIL_REFLECT=3, FAIL_MODE_COUNT=4;
679
void testWithMember(Member mem,
680
Lookup lookup, // initial lookup of member => MH
681
Lookup revLookup, // reveal MH => info
682
Lookup refLookup, // reflect info => member
683
int failureMode) throws Throwable {
684
boolean expectEx1 = (failureMode == FAIL_LOOKUP); // testOnMembersNoLookup
685
boolean expectEx2 = (failureMode == FAIL_REVEAL); // testOnMembersNoReveal
686
boolean expectEx3 = (failureMode == FAIL_REFLECT); // testOnMembersNoReflect
687
for (int variation = 0; ; variation++) {
688
UnreflectResult res = unreflectMember(lookup, mem, variation);
689
failureModeCounts[failureMode] += 1;
690
if (variation == 0) assert(res != null);
691
if (res == null) break;
692
if (VERBOSE && variation == 0)
693
System.out.println("from "+mem.getDeclaringClass().getSimpleName());
694
MethodHandle mh = res.mh;
695
Throwable ex1 = res.ex;
696
if (VERBOSE) System.out.println(" "+variation+": "+res+" << "+(mh != null ? mh : ex1));
697
if (expectEx1 && ex1 != null)
698
continue; // this is OK; we expected that lookup to fail
699
if (expectEx1)
700
throw new AssertionError("unexpected lookup for negative test");
701
if (ex1 != null && !expectEx1) {
702
if (failureMode != NO_FAIL)
703
throw new AssertionError("unexpected lookup failure for negative test", ex1);
704
throw ex1;
705
}
706
MethodHandleInfo info;
707
try {
708
info = revLookup.revealDirect(mh);
709
if (expectEx2) throw new AssertionError("unexpected revelation for negative test");
710
} catch (IllegalArgumentException|SecurityException ex2) {
711
if (VERBOSE) System.out.println(" "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2);
712
if (expectEx2)
713
continue; // this is OK; we expected the reflect to fail
714
if (failureMode != NO_FAIL)
715
throw new AssertionError("unexpected revelation failure for negative test", ex2);
716
throw ex2;
717
}
718
assert(consistent(res, info));
719
Member mem2;
720
try {
721
mem2 = info.reflectAs(Member.class, refLookup);
722
if (expectEx3) throw new AssertionError("unexpected reflection for negative test");
723
assert(!(mem instanceof SignaturePolymorphicMethod));
724
} catch (IllegalArgumentException ex3) {
725
if (VERBOSE) System.out.println(" "+variation+": "+info+" => (EX3)"+ex3);
726
if (expectEx3)
727
continue; // this is OK; we expected the reflect to fail
728
if (mem instanceof SignaturePolymorphicMethod)
729
continue; // this is OK; we cannot reflect MH.invokeExact(a,b,c)
730
if (failureMode != NO_FAIL)
731
throw new AssertionError("unexpected reflection failure for negative test", ex3);
732
throw ex3;
733
}
734
assert(consistent(mem, mem2));
735
UnreflectResult res2 = unreflectMember(lookup, mem2, variation);
736
MethodHandle mh2 = res2.mh;
737
assert(consistent(mh, mh2));
738
MethodHandleInfo info2 = lookup.revealDirect(mh2);
739
assert(consistent(info, info2));
740
assert(consistent(res, info2));
741
Member mem3;
742
if (hasSM())
743
mem3 = info2.reflectAs(Member.class, lookup);
744
else
745
mem3 = MethodHandles.reflectAs(Member.class, mh2);
746
assert(consistent(mem2, mem3));
747
if (hasSM()) {
748
try {
749
MethodHandles.reflectAs(Member.class, mh2);
750
throw new AssertionError("failed to throw on "+mem3);
751
} catch (SecurityException ex3) {
752
// OK...
753
}
754
}
755
}
756
}
757
}
758
759