--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Mon Aug 12 19:57:21 2013 +0400
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Mon Aug 12 13:47:21 2013 -0700
@@ -1289,6 +1289,10 @@
: resolveOrFail(refKind, defc, name, (Class<?>) type);
return getDirectField(refKind, defc, field);
} else if (MethodHandleNatives.refKindIsMethod(refKind)) {
+ if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
+ MethodHandle mh = findVirtualForMH(name, (MethodType) type);
+ if (mh != null) return mh;
+ }
MemberName method = (resolved != null) ? resolved
: resolveOrFail(refKind, defc, name, (MethodType) type);
return getDirectMethod(refKind, defc, method, lookupClass);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/MethodHandleConstants.java Mon Aug 12 13:47:21 2013 -0700
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8022066
+ * @summary smoke test for method handle constants
+ * @build indify.Indify
+ * @compile MethodHandleConstants.java
+ * @run main/othervm
+ * indify.Indify
+ * --verify-specifier-count=0
+ * --expand-properties --classpath ${test.classes}
+ * --java test.java.lang.invoke.MethodHandleConstants --check-output
+ * @run main/othervm
+ * indify.Indify
+ * --expand-properties --classpath ${test.classes}
+ * --java test.java.lang.invoke.MethodHandleConstants --security-manager
+ */
+
+package test.java.lang.invoke;
+
+import java.util.*;
+import java.io.*;
+import java.lang.invoke.*;
+import java.security.*;
+
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class MethodHandleConstants {
+ public static void main(String... av) throws Throwable {
+ if (av.length > 0 && av[0].equals("--check-output")) openBuf();
+ if (av.length > 0 && av[0].equals("--security-manager")) setSM();
+ System.out.println("Obtaining method handle constants:");
+ testCase(MH_String_replace_C2(), String.class, "replace", String.class, String.class, char.class, char.class);
+ testCase(MH_MethodHandle_invokeExact_SC2(), MethodHandle.class, "invokeExact", String.class, MethodHandle.class, String.class, char.class, char.class);
+ testCase(MH_MethodHandle_invoke_SC2(), MethodHandle.class, "invoke", String.class, MethodHandle.class, String.class, char.class, char.class);
+ testCase(MH_Class_forName_S(), Class.class, "forName", Class.class, String.class);
+ testCase(MH_Class_forName_SbCL(), Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class);
+ System.out.println("Done.");
+ closeBuf();
+ }
+
+ private static void testCase(MethodHandle mh, Class<?> defc, String name, Class<?> rtype, Class<?>... ptypes) throws Throwable {
+ System.out.println(mh);
+ // we include defc, because we assume it is a non-static MH:
+ MethodType mt = methodType(rtype, ptypes);
+ assertEquals(mh.type(), mt);
+ // FIXME: Use revealDirect to find out more
+ }
+ private static void assertEquals(Object exp, Object act) {
+ if (exp == act || (exp != null && exp.equals(act))) return;
+ throw new AssertionError("not equal: "+exp+", "+act);
+ }
+
+ private static void setSM() {
+ Policy.setPolicy(new TestPolicy());
+ System.setSecurityManager(new SecurityManager());
+ }
+
+ private static PrintStream oldOut;
+ private static ByteArrayOutputStream buf;
+ private static void openBuf() {
+ oldOut = System.out;
+ buf = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(buf));
+ }
+ private static void closeBuf() {
+ if (buf == null) return;
+ System.out.flush();
+ System.setOut(oldOut);
+ String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
+ for (String line : haveLines) System.out.println(line);
+ Iterator<String> iter = Arrays.asList(haveLines).iterator();
+ for (String want : EXPECT_OUTPUT) {
+ String have = iter.hasNext() ? iter.next() : "[EOF]";
+ if (want.equals(have)) continue;
+ System.err.println("want line: "+want);
+ System.err.println("have line: "+have);
+ throw new AssertionError("unexpected output: "+have);
+ }
+ if (iter.hasNext())
+ throw new AssertionError("unexpected output: "+iter.next());
+ }
+ private static final String[] EXPECT_OUTPUT = {
+ "Obtaining method handle constants:",
+ "MethodHandle(String,char,char)String",
+ "MethodHandle(MethodHandle,String,char,char)String",
+ "MethodHandle(MethodHandle,String,char,char)String",
+ "MethodHandle(String)Class",
+ "MethodHandle(String,boolean,ClassLoader)Class",
+ "Done."
+ };
+
+ // String.replace(String, char, char)
+ private static MethodType MT_String_replace_C2() {
+ shouldNotCallThis();
+ return methodType(String.class, char.class, char.class);
+ }
+ private static MethodHandle MH_String_replace_C2() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findVirtual(String.class, "replace", MT_String_replace_C2());
+ }
+
+ // MethodHandle.invokeExact(...)
+ private static MethodType MT_MethodHandle_invokeExact_SC2() {
+ shouldNotCallThis();
+ return methodType(String.class, String.class, char.class, char.class);
+ }
+ private static MethodHandle MH_MethodHandle_invokeExact_SC2() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findVirtual(MethodHandle.class, "invokeExact", MT_MethodHandle_invokeExact_SC2());
+ }
+
+ // MethodHandle.invoke(...)
+ private static MethodType MT_MethodHandle_invoke_SC2() {
+ shouldNotCallThis();
+ return methodType(String.class, String.class, char.class, char.class);
+ }
+ private static MethodHandle MH_MethodHandle_invoke_SC2() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findVirtual(MethodHandle.class, "invoke", MT_MethodHandle_invoke_SC2());
+ }
+
+ // Class.forName(String)
+ private static MethodType MT_Class_forName_S() {
+ shouldNotCallThis();
+ return methodType(Class.class, String.class);
+ }
+ private static MethodHandle MH_Class_forName_S() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findStatic(Class.class, "forName", MT_Class_forName_S());
+ }
+
+ // Class.forName(String, boolean, ClassLoader)
+ private static MethodType MT_Class_forName_SbCL() {
+ shouldNotCallThis();
+ return methodType(Class.class, String.class, boolean.class, ClassLoader.class);
+ }
+ private static MethodHandle MH_Class_forName_SbCL() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findStatic(Class.class, "forName", MT_Class_forName_SbCL());
+ }
+
+ private static void shouldNotCallThis() {
+ // if this gets called, the transformation has not taken place
+ if (System.getProperty("MethodHandleConstants.allow-untransformed") != null) return;
+ throw new AssertionError("this code should be statically transformed away by Indify");
+ }
+
+ static class TestPolicy extends Policy {
+ final PermissionCollection permissions = new Permissions();
+ TestPolicy() {
+ permissions.add(new java.io.FilePermission("<<ALL FILES>>", "read"));
+ }
+ public PermissionCollection getPermissions(ProtectionDomain domain) {
+ return permissions;
+ }
+
+ public PermissionCollection getPermissions(CodeSource codesource) {
+ return permissions;
+ }
+
+ public boolean implies(ProtectionDomain domain, Permission perm) {
+ return permissions.implies(perm);
+ }
+ }
+}