1 /* 2 * Copyright (c) 2016, 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 package jdk.vm.ci.hotspot.test; 25 26 import java.io.File; 27 import java.lang.invoke.MethodHandle; 28 import java.lang.invoke.MethodHandles; 29 import java.lang.invoke.MethodType; 30 import java.net.MalformedURLException; 31 import java.net.URL; 32 import java.net.URLClassLoader; 33 import java.nio.file.Paths; 34 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; 35 import jdk.vm.ci.meta.JavaConstant; 36 import jdk.vm.ci.meta.MetaAccessProvider; 37 import jdk.vm.ci.meta.MethodHandleAccessProvider; 38 import jdk.vm.ci.runtime.JVMCI; 39 import org.testng.annotations.DataProvider; 40 41 public class MethodHandleAccessProviderData implements TestInterface { 42 private static final MetaAccessProvider META_ACCESS = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); 43 private static final HotSpotConstantReflectionProvider CONSTANT_REFLECTION = (HotSpotConstantReflectionProvider) JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection(); 44 // see DirectMethodHandle.java to check invoke* method names assignment 45 private static final String IVIRTUAL_RESOLVED_NAME = "invokeVirtual"; 46 private static final String ISTATIC_RESOLVED_NAME = "invokeStatic"; 47 private static final String ISPECIAL_RESOLVED_NAME = "invokeSpecial"; 48 private static final String ISTATICINIT_RESOLVED_NAME = "invokeStaticInit"; 49 private static final String IINTERFACE_RESOLVED_NAME = "invokeInterface"; 50 private static final String INEWSPECIAL_RESOLVED_NAME = "newInvokeSpecial"; 51 52 @DataProvider(name = "intrinsicsPositive") 53 public static Object[][] getIntrinsicsDataPositive() { 54 Object[][] result; 55 try { 56 result = new Object[][]{ 57 new Object[]{ 58 META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("invokeBasic", Object[].class)), 59 MethodHandleAccessProvider.IntrinsicMethod.INVOKE_BASIC}, 60 new Object[]{ 61 META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("linkToInterface", Object[].class)), 62 MethodHandleAccessProvider.IntrinsicMethod.LINK_TO_INTERFACE}, 63 new Object[]{ 64 META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("linkToStatic", Object[].class)), 65 MethodHandleAccessProvider.IntrinsicMethod.LINK_TO_STATIC}, 66 new Object[]{ 67 META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("linkToVirtual", Object[].class)), 68 MethodHandleAccessProvider.IntrinsicMethod.LINK_TO_VIRTUAL}, 69 new Object[]{ 70 META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("linkToSpecial", Object[].class)), 71 MethodHandleAccessProvider.IntrinsicMethod.LINK_TO_SPECIAL}}; 72 } catch (NoSuchMethodException e) { 73 throw new Error("TESTBUG: can't find method: " + e, e); 74 } 75 return result; 76 } 77 78 @DataProvider(name = "intrinsicsNegative") 79 public static Object[][] getIntrinsicsDataNegative() { 80 Object[][] result; 81 try { 82 result = new Object[][]{new Object[]{META_ACCESS.lookupJavaMethod(MethodHandle.class.getDeclaredMethod("invokeWithArguments", Object[].class))}}; 83 } catch (NoSuchMethodException e) { 84 throw new Error("TESTBUG: can't find method: " + e, e); 85 } 86 return result; 87 } 88 89 @DataProvider(name = "invokeBasicNegative1") 90 public static Object[][] getInvokeBasicDataNegative1() { 91 Object[][] result; 92 JavaConstant wrongObject = CONSTANT_REFLECTION.forObject("42"); 93 // 2nd parameter is force bytecode generation = true/false 94 result = new Object[][]{ 95 new Object[]{wrongObject, true}, 96 new Object[]{wrongObject, false}, 97 new Object[]{JavaConstant.NULL_POINTER, true}, 98 new Object[]{JavaConstant.NULL_POINTER, false}}; 99 return result; 100 } 101 102 @DataProvider(name = "invokeBasicNegative2") 103 public static Object[][] getInvokeBasicDataNegative2() { 104 Object[][] result; 105 // 2nd parameter is force bytecode generation = true/false 106 result = new Object[][]{ 107 new Object[]{null, true}, 108 new Object[]{null, false}}; 109 return result; 110 } 111 112 @DataProvider(name = "invokeBasicPositive") 113 public static Object[][] getInvokeBasicDataPositive() { 114 Object[][] result; 115 MethodHandle mhIVirtual; 116 MethodHandle mhIStatic; 117 MethodHandle mhISpecial; 118 MethodHandle mhIStaticInit; 119 MethodHandle mhINewSpecial; 120 MethodHandle mhIInterface; 121 MethodHandles.Lookup lookup = MethodHandles.lookup(); 122 MethodType voidRet = MethodType.methodType(void.class); 123 Class<?> self = MethodHandleAccessProviderData.class; 124 // let's get a separate, thus, not initialized class 125 ClassLoader current = self.getClassLoader(); 126 String[] cpaths = System.getProperty("java.class.path").split(File.pathSeparator); 127 URL[] urls = new URL[cpaths.length]; 128 try { 129 for (int i = 0; i < cpaths.length; i++) { 130 urls[i] = Paths.get(cpaths[i]).toUri().toURL(); 131 } 132 } catch (MalformedURLException e) { 133 throw new Error("Can't parse classpath url: " + e, e); 134 } 135 Class<?> clone; 136 try { 137 clone = new ParentLastURLClassLoader(urls, current).loadClass(self.getName()); 138 } catch (ClassNotFoundException e) { 139 throw new Error("TESTBUG: can't find class: " + e, e); 140 } 141 try { 142 mhIVirtual = lookup.findVirtual(self, "publicMethod", voidRet); 143 mhIStatic = lookup.findStatic(self, "staticMethod", voidRet); 144 mhISpecial = lookup.findSpecial(self, "privateMethod", voidRet, self); 145 mhIStaticInit = lookup.findStatic(clone, "staticMethod", voidRet); 146 mhINewSpecial = lookup.findConstructor(self, voidRet); 147 mhIInterface = lookup.findVirtual(TestInterface.class, "interfaceMethod", voidRet); 148 } catch (NoSuchMethodException | IllegalAccessException e) { 149 throw new Error("TESTBUG: lookup failed: " + e, e); 150 } 151 JavaConstant jcIVirtual = CONSTANT_REFLECTION.forObject(mhIVirtual); 152 JavaConstant jcIStatic = CONSTANT_REFLECTION.forObject(mhIStatic); 153 JavaConstant jcISpecial = CONSTANT_REFLECTION.forObject(mhISpecial); 154 JavaConstant jcIStaticInit = CONSTANT_REFLECTION.forObject(mhIStaticInit); 155 JavaConstant jcINewSpecial = CONSTANT_REFLECTION.forObject(mhINewSpecial); 156 JavaConstant jcIInterface = CONSTANT_REFLECTION.forObject(mhIInterface); 157 // 2nd parameter is force bytecode generation = true/false 158 result = new Object[][]{ 159 new Object[]{jcIVirtual, true, IVIRTUAL_RESOLVED_NAME}, 160 new Object[]{jcIVirtual, false, IVIRTUAL_RESOLVED_NAME}, 161 new Object[]{jcIStatic, true, ISTATIC_RESOLVED_NAME}, 162 new Object[]{jcIStatic, false, ISTATIC_RESOLVED_NAME}, 163 new Object[]{jcISpecial, true, ISPECIAL_RESOLVED_NAME}, 164 new Object[]{jcISpecial, false, ISPECIAL_RESOLVED_NAME}, 165 new Object[]{jcIStaticInit, true, ISTATICINIT_RESOLVED_NAME}, 166 new Object[]{jcIStaticInit, false, ISTATICINIT_RESOLVED_NAME}, 167 new Object[]{jcINewSpecial, false, INEWSPECIAL_RESOLVED_NAME}, 168 new Object[]{jcINewSpecial, true, INEWSPECIAL_RESOLVED_NAME}, 169 new Object[]{jcIInterface, false, IINTERFACE_RESOLVED_NAME}, 170 new Object[]{jcIInterface, true, IINTERFACE_RESOLVED_NAME}}; 171 return result; 172 } 173 174 // can't use nested classes for storing these test methods. see JDK-8010319 175 private void privateMethod() { 176 // empty 177 } 178 179 public static void staticMethod() { 180 // empty 181 } 182 183 public void publicMethod() { 184 // empty 185 } 186 187 @Override 188 public void interfaceMethod() { 189 // empty 190 } 191 } 192 193 interface TestInterface { 194 void interfaceMethod(); 195 } 196 197 class ParentLastURLClassLoader extends URLClassLoader { 198 199 ParentLastURLClassLoader(URL[] urls, ClassLoader parent) { 200 super(urls, parent); 201 } 202 203 @Override 204 public Class<?> loadClass(String name) throws ClassNotFoundException { 205 try { 206 Class<?> c = findClass(name); 207 if (c != null) { 208 return c; 209 } 210 } catch (ClassNotFoundException e) { 211 // ignore 212 } 213 return super.loadClass(name); 214 } 215 }