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