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