Path: blob/master/test/jdk/java/lang/invoke/7087570/Test7087570.java
41153 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/* @test24* @bug 708757025* @summary REF_invokeSpecial DMHs (which are unusual) get marked explicitly; tweak the MHI to use this bit26*27* @run main Test708757028*/2930import java.lang.invoke.*;31import java.lang.reflect.*;32import java.util.*;3334import static java.lang.invoke.MethodHandles.*;35import static java.lang.invoke.MethodType.*;36import static java.lang.invoke.MethodHandleInfo.*;3738public class Test7087570 {3940private static final TestMethodData[] TESTS = new TestMethodData[] {41// field accessors42data(DummyFieldHolder.class, "instanceField", getterMethodType(String.class), DummyFieldHolder.class, REF_getField),43data(DummyFieldHolder.class, "instanceField", setterMethodType(String.class), DummyFieldHolder.class, REF_putField),44data(DummyFieldHolder.class, "staticField", getterMethodType(Integer.class), DummyFieldHolder.class, REF_getStatic),45data(DummyFieldHolder.class, "staticField", setterMethodType(Integer.class), DummyFieldHolder.class, REF_putStatic),46data(DummyFieldHolder.class, "instanceByteField", getterMethodType(byte.class), DummyFieldHolder.class, REF_getField),47data(DummyFieldHolder.class, "instanceByteField", setterMethodType(byte.class), DummyFieldHolder.class, REF_putField),4849// REF_invokeVirtual50data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeVirtual),5152// REF_invokeVirtual strength-reduced to REF_invokeSpecial,53// test if it normalizes back to REF_invokeVirtual in MethodHandleInfo as expected54data(String.class, "hashCode", methodType(int.class), String.class, REF_invokeVirtual),5556// REF_invokeStatic57data(Collections.class, "sort", methodType(void.class, List.class), Collections.class, REF_invokeStatic),58data(Arrays.class, "asList", methodType(List.class, Object[].class), Arrays.class, REF_invokeStatic), // varargs case5960// REF_invokeSpecial61data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeSpecial),6263// REF_newInvokeSpecial64data(String.class, "<init>", methodType(void.class, char[].class), String.class, REF_newInvokeSpecial),65data(DummyFieldHolder.class, "<init>", methodType(void.class, byte.class, Long[].class), DummyFieldHolder.class, REF_newInvokeSpecial), // varargs case6667// REF_invokeInterface68data(List.class, "size", methodType(int.class), List.class, REF_invokeInterface)69};7071public static void main(String... args) throws Throwable {72testWithLookup();73testWithUnreflect();74}7576private static void doTest(MethodHandle mh, TestMethodData testMethod) {77MethodHandleInfo mhi = LOOKUP.revealDirect(mh);7879System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n",80testMethod.clazz.getName(), testMethod.name, testMethod.methodType,81referenceKindToString(testMethod.referenceKind),82referenceKindToString(mhi.getReferenceKind()));83assertEquals(testMethod.name, mhi.getName());84assertEquals(testMethod.methodType, mhi.getMethodType());85assertEquals(testMethod.declaringClass, mhi.getDeclaringClass());86assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh));87assertRefKindEquals(testMethod.referenceKind, mhi.getReferenceKind());88}8990private static void testWithLookup() throws Throwable {91for (TestMethodData testMethod : TESTS) {92MethodHandle mh = lookupFrom(testMethod);93doTest(mh, testMethod);94}95}9697private static void testWithUnreflect() throws Throwable {98for (TestMethodData testMethod : TESTS) {99MethodHandle mh = unreflectFrom(testMethod);100doTest(mh, testMethod);101}102}103104private static MethodType getterMethodType(Class<?> clazz) {105return methodType(clazz);106}107108private static MethodType setterMethodType(Class<?> clazz) {109return methodType(void.class, clazz);110}111112private static final Lookup LOOKUP = lookup();113114private static class TestMethodData {115final Class<?> clazz;116final String name;117final MethodType methodType;118final Class<?> declaringClass;119final int referenceKind; // the nominal refKind120121public TestMethodData(Class<?> clazz, String name,122MethodType methodType, Class<?> declaringClass,123int referenceKind) {124this.clazz = clazz;125this.name = name;126this.methodType = methodType;127this.declaringClass = declaringClass;128this.referenceKind = referenceKind;129}130}131132private static TestMethodData data(Class<?> clazz, String name,133MethodType methodType, Class<?> declaringClass,134int referenceKind) {135return new TestMethodData(clazz, name, methodType, declaringClass, referenceKind);136}137138private static MethodHandle lookupFrom(TestMethodData testMethod)139throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {140switch (testMethod.referenceKind) {141case REF_getField:142return LOOKUP.findGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType());143case REF_putField:144return LOOKUP.findSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0));145case REF_getStatic:146return LOOKUP.findStaticGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType());147case REF_putStatic:148return LOOKUP.findStaticSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0));149case REF_invokeVirtual:150case REF_invokeInterface:151return LOOKUP.findVirtual(testMethod.clazz, testMethod.name, testMethod.methodType);152case REF_invokeStatic:153return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType);154case REF_invokeSpecial:155Class<?> thisClass = LOOKUP.lookupClass();156MethodHandle smh = LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass);157noteInvokeSpecial(smh);158return smh;159case REF_newInvokeSpecial:160return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType);161default:162throw new Error("ERROR: unexpected referenceKind in test data");163}164}165166private static MethodHandle unreflectFrom(TestMethodData testMethod)167throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {168switch (testMethod.referenceKind) {169case REF_getField:170case REF_getStatic: {171Field f = testMethod.clazz.getDeclaredField(testMethod.name);172return LOOKUP.unreflectGetter(f);173}174case REF_putField:175case REF_putStatic: {176Field f = testMethod.clazz.getDeclaredField(testMethod.name);177return LOOKUP.unreflectSetter(f);178}179case REF_invokeVirtual:180case REF_invokeStatic:181case REF_invokeInterface: {182Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray());183return LOOKUP.unreflect(m);184}185case REF_invokeSpecial: {186Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray());187Class<?> thisClass = LOOKUP.lookupClass();188MethodHandle smh = LOOKUP.unreflectSpecial(m, thisClass);189noteInvokeSpecial(smh);190return smh;191}192case REF_newInvokeSpecial: {193Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray());194return LOOKUP.unreflectConstructor(c);195}196default:197throw new Error("ERROR: unexpected referenceKind in test data");198}199}200201private static List<MethodHandle> specialMethodHandles = new ArrayList<>();202private static void noteInvokeSpecial(MethodHandle mh) {203specialMethodHandles.add(mh);204assert(isInvokeSpecial(mh));205}206private static boolean isInvokeSpecial(MethodHandle mh) {207return specialMethodHandles.contains(mh);208}209210private static void assertRefKindEquals(int expect, int observed) {211if (expect == observed) return;212213String msg = "expected " + referenceKindToString(expect) +214" but observed " + referenceKindToString(observed);215System.out.println("FAILED: " + msg);216throw new AssertionError(msg);217}218219private static void assertEquals(Object expect, Object observed) {220if (java.util.Objects.equals(expect, observed)) return;221222String msg = "expected " + expect + " but observed " + observed;223System.out.println("FAILED: " + msg);224throw new AssertionError(msg);225}226}227228class DummyFieldHolder {229public static Integer staticField;230public String instanceField;231public byte instanceByteField;232233public DummyFieldHolder(byte unused1, Long... unused2) {234}235}236237238239