1 /* 2 * Copyright (c) 2010, 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 /* @test 25 * @bug 8022066 26 * @summary smoke test for method handle constants 27 * @build indify.Indify 28 * @compile MethodHandleConstants.java 29 * @run main/othervm 30 * indify.Indify 31 * --verify-specifier-count=0 32 * --expand-properties --classpath ${test.classes} 33 * --java test.java.lang.invoke.MethodHandleConstants --check-output 34 * @run main/othervm 35 * indify.Indify 36 * --expand-properties --classpath ${test.classes} 37 * --java test.java.lang.invoke.MethodHandleConstants --security-manager 38 */ 39 40 package test.java.lang.invoke; 41 42 import java.util.*; 43 import java.io.*; 44 import java.lang.invoke.*; 45 import java.security.*; 46 47 import static java.lang.invoke.MethodHandles.*; 48 import static java.lang.invoke.MethodType.*; 49 50 public class MethodHandleConstants { 51 public static void main(String... av) throws Throwable { 52 if (av.length > 0 && av[0].equals("--check-output")) openBuf(); 53 if (av.length > 0 && av[0].equals("--security-manager")) setSM(); 54 System.out.println("Obtaining method handle constants:"); 55 testCase(MH_String_replace_C2(), String.class, "replace", String.class, String.class, char.class, char.class); 56 testCase(MH_MethodHandle_invokeExact_SC2(), MethodHandle.class, "invokeExact", String.class, MethodHandle.class, String.class, char.class, char.class); 57 testCase(MH_MethodHandle_invoke_SC2(), MethodHandle.class, "invoke", String.class, MethodHandle.class, String.class, char.class, char.class); 58 testCase(MH_Class_forName_S(), Class.class, "forName", Class.class, String.class); 59 testCase(MH_Class_forName_SbCL(), Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class); 60 System.out.println("Done."); 61 closeBuf(); 62 } 63 64 private static void testCase(MethodHandle mh, Class<?> defc, String name, Class<?> rtype, Class<?>... ptypes) throws Throwable { 65 System.out.println(mh); 66 // we include defc, because we assume it is a non-static MH: 67 MethodType mt = methodType(rtype, ptypes); 68 assertEquals(mh.type(), mt); 69 // FIXME: Use revealDirect to find out more 70 } 71 private static void assertEquals(Object exp, Object act) { 72 if (exp == act || (exp != null && exp.equals(act))) return; 73 throw new AssertionError("not equal: "+exp+", "+act); 74 } 75 76 private static void setSM() { 77 Policy.setPolicy(new TestPolicy()); 78 System.setSecurityManager(new SecurityManager()); 79 } 80 81 private static PrintStream oldOut; 82 private static ByteArrayOutputStream buf; 83 private static void openBuf() { 84 oldOut = System.out; 85 buf = new ByteArrayOutputStream(); 86 System.setOut(new PrintStream(buf)); 87 } 88 private static void closeBuf() { 89 if (buf == null) return; 90 System.out.flush(); 91 System.setOut(oldOut); 92 String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+"); 93 for (String line : haveLines) System.out.println(line); 94 Iterator<String> iter = Arrays.asList(haveLines).iterator(); 95 for (String want : EXPECT_OUTPUT) { 96 String have = iter.hasNext() ? iter.next() : "[EOF]"; 97 if (want.equals(have)) continue; 98 System.err.println("want line: "+want); 99 System.err.println("have line: "+have); 100 throw new AssertionError("unexpected output: "+have); 101 } 102 if (iter.hasNext()) 103 throw new AssertionError("unexpected output: "+iter.next()); 104 } 105 private static final String[] EXPECT_OUTPUT = { 106 "Obtaining method handle constants:", 107 "MethodHandle(String,char,char)String", 108 "MethodHandle(MethodHandle,String,char,char)String", 109 "MethodHandle(MethodHandle,String,char,char)String", 110 "MethodHandle(String)Class", 111 "MethodHandle(String,boolean,ClassLoader)Class", 112 "Done." 113 }; 114 115 // String.replace(String, char, char) 116 private static MethodType MT_String_replace_C2() { 117 shouldNotCallThis(); 118 return methodType(String.class, char.class, char.class); 119 } 120 private static MethodHandle MH_String_replace_C2() throws ReflectiveOperationException { 121 shouldNotCallThis(); 122 return lookup().findVirtual(String.class, "replace", MT_String_replace_C2()); 123 } 124 125 // MethodHandle.invokeExact(...) 126 private static MethodType MT_MethodHandle_invokeExact_SC2() { 127 shouldNotCallThis(); 128 return methodType(String.class, String.class, char.class, char.class); 129 } 130 private static MethodHandle MH_MethodHandle_invokeExact_SC2() throws ReflectiveOperationException { 131 shouldNotCallThis(); 132 return lookup().findVirtual(MethodHandle.class, "invokeExact", MT_MethodHandle_invokeExact_SC2()); 133 } 134 135 // MethodHandle.invoke(...) 136 private static MethodType MT_MethodHandle_invoke_SC2() { 137 shouldNotCallThis(); 138 return methodType(String.class, String.class, char.class, char.class); 139 } 140 private static MethodHandle MH_MethodHandle_invoke_SC2() throws ReflectiveOperationException { 141 shouldNotCallThis(); 142 return lookup().findVirtual(MethodHandle.class, "invoke", MT_MethodHandle_invoke_SC2()); 143 } 144 145 // Class.forName(String) 146 private static MethodType MT_Class_forName_S() { 147 shouldNotCallThis(); 148 return methodType(Class.class, String.class); 149 } 150 private static MethodHandle MH_Class_forName_S() throws ReflectiveOperationException { 151 shouldNotCallThis(); 152 return lookup().findStatic(Class.class, "forName", MT_Class_forName_S()); 153 } 154 155 // Class.forName(String, boolean, ClassLoader) 156 private static MethodType MT_Class_forName_SbCL() { 157 shouldNotCallThis(); 158 return methodType(Class.class, String.class, boolean.class, ClassLoader.class); 159 } 160 private static MethodHandle MH_Class_forName_SbCL() throws ReflectiveOperationException { 161 shouldNotCallThis(); 162 return lookup().findStatic(Class.class, "forName", MT_Class_forName_SbCL()); 163 } 164 165 private static void shouldNotCallThis() { 166 // if this gets called, the transformation has not taken place 167 if (System.getProperty("MethodHandleConstants.allow-untransformed") != null) return; 168 throw new AssertionError("this code should be statically transformed away by Indify"); 169 } 170 171 static class TestPolicy extends Policy { 172 final PermissionCollection permissions = new Permissions(); 173 TestPolicy() { 174 permissions.add(new java.io.FilePermission("<<ALL FILES>>", "read")); 175 } 176 public PermissionCollection getPermissions(ProtectionDomain domain) { 177 return permissions; 178 } 179 180 public PermissionCollection getPermissions(CodeSource codesource) { 181 return permissions; 182 } 183 184 public boolean implies(ProtectionDomain domain, Permission perm) { 185 return permissions.implies(perm); 186 } 187 } 188 }