1 /* 2 * Copyright (c) 2017, 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 /* 25 * @test 26 * @bug 8035776 8173587 27 * @summary metafactory should fail if instantiatedMethodType does not match sam/bridge descriptors 28 */ 29 import java.lang.invoke.*; 30 import java.util.*; 31 32 public class MetafactoryDescriptorTest { 33 34 static final MethodHandles.Lookup lookup = MethodHandles.lookup(); 35 mt(Class<?> ret, Class<?>... params)36 static MethodType mt(Class<?> ret, Class<?>... params) { 37 return MethodType.methodType(ret, params); 38 } 39 40 public interface I {} 41 42 public static class C { m_void(String arg)43 public static void m_void(String arg) {} m_boolean(String arg)44 public static boolean m_boolean(String arg) { return true; } m_char(String arg)45 public static char m_char(String arg) { return 'x'; } m_byte(String arg)46 public static byte m_byte(String arg) { return 12; } m_short(String arg)47 public static short m_short(String arg) { return 12; } m_int(String arg)48 public static int m_int(String arg) { return 12; } m_long(String arg)49 public static long m_long(String arg) { return 12; } m_float(String arg)50 public static float m_float(String arg) { return 12; } m_double(String arg)51 public static double m_double(String arg) { return 12; } m_String(String arg)52 public static String m_String(String arg) { return ""; } m_Integer(String arg)53 public static Integer m_Integer(String arg) { return 23; } m_Object(String arg)54 public static Object m_Object(String arg) { return new Object(); } 55 n_boolean(boolean arg)56 public static String n_boolean(boolean arg) { return ""; } n_char(char arg)57 public static String n_char(char arg) { return ""; } n_byte(byte arg)58 public static String n_byte(byte arg) { return ""; } n_short(short arg)59 public static String n_short(short arg) { return ""; } n_int(int arg)60 public static String n_int(int arg) { return ""; } n_long(long arg)61 public static String n_long(long arg) { return ""; } n_float(float arg)62 public static String n_float(float arg) { return ""; } n_double(double arg)63 public static String n_double(double arg) { return ""; } n_String(String arg)64 public static String n_String(String arg) { return ""; } n_Integer(Integer arg)65 public static String n_Integer(Integer arg) { return ""; } n_Object(Object arg)66 public static String n_Object(Object arg) { return ""; } 67 getM(Class<?> c)68 public static MethodHandle getM(Class<?> c) { 69 try { 70 return lookup.findStatic(C.class, "m_" + c.getSimpleName(), mt(c, String.class)); 71 } 72 catch (NoSuchMethodException | IllegalAccessException e) { 73 throw new RuntimeException(e); 74 } 75 } 76 getN(Class<?> c)77 public static MethodHandle getN(Class<?> c) { 78 if (c == void.class) return null; 79 try { 80 return lookup.findStatic(C.class, "n_" + c.getSimpleName(), mt(String.class, c)); 81 } 82 catch (NoSuchMethodException | IllegalAccessException e) { 83 throw new RuntimeException(e); 84 } 85 } 86 87 } 88 main(String... args)89 public static void main(String... args) { 90 Class<?>[] t = { void.class, boolean.class, char.class, 91 byte.class, short.class, int.class, long.class, float.class, double.class, 92 String.class, Integer.class, Object.class }; 93 94 for (int i = 0; i < t.length; i++) { 95 MethodHandle m = C.getM(t[i]); 96 MethodHandle n = C.getN(t[i]); // null for void.class 97 for (int j = 0; j < t.length; j++) { 98 boolean correctRet = t[j].isAssignableFrom(t[i]) || conversions.contains(t[i], t[j]); 99 test(correctRet, m, mt(t[i], String.class), mt(t[j], String.class)); 100 testBridge(correctRet, m, mt(t[i], String.class), mt(t[i], String.class), 101 mt(t[j], Object.class)); 102 testBridge(correctRet, m, mt(t[i], String.class), mt(t[i], String.class), 103 mt(t[i], CharSequence.class), mt(t[j], Object.class)); 104 105 if (t[i] != void.class && t[j] != void.class) { 106 boolean correctParam = t[j].isAssignableFrom(t[i]); 107 test(correctParam, n, mt(String.class, t[i]), mt(String.class, t[j])); 108 testBridge(correctParam, n, mt(String.class, t[i]), mt(String.class, t[i]), 109 mt(Object.class, t[j])); 110 testBridge(correctParam, n, mt(String.class, t[i]), mt(String.class, t[i]), 111 mt(CharSequence.class, t[i]), mt(Object.class, t[j])); 112 } 113 114 } 115 } 116 } 117 test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT)118 static void test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) { 119 tryMetafactory(correct, mh, instMT, samMT); 120 tryAltMetafactory(correct, mh, instMT, samMT); 121 } 122 testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs)123 static void testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { 124 tryAltMetafactory(correct, mh, instMT, samMT, bridgeMTs); 125 } 126 tryMetafactory(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT)127 static void tryMetafactory(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) { 128 try { 129 LambdaMetafactory.metafactory(lookup, "run", mt(I.class), 130 samMT, mh, instMT); 131 if (!correct) { 132 throw new AssertionError("Unexpected linkage without error:" + 133 " impl=" + mh + 134 ", inst=" + instMT + 135 ", sam=" + samMT); 136 } 137 } 138 catch (LambdaConversionException e) { 139 if (correct) { 140 throw new AssertionError("Unexpected linkage error:" + 141 " e=" + e + 142 ", impl=" + mh + 143 ", inst=" + instMT + 144 ", sam=" + samMT); 145 } 146 } 147 } 148 tryAltMetafactory(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs)149 static void tryAltMetafactory(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, 150 MethodType... bridgeMTs) { 151 boolean bridge = bridgeMTs.length > 0; 152 Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4]; 153 args[0] = samMT; 154 args[1] = mh; 155 args[2] = instMT; 156 args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0; 157 if (bridge) { 158 args[4] = bridgeMTs.length; 159 for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i]; 160 } 161 try { 162 LambdaMetafactory.altMetafactory(lookup, "run", mt(I.class), args); 163 if (!correct) { 164 throw new AssertionError("Unexpected linkage without error:" + 165 " impl=" + mh + 166 ", inst=" + instMT + 167 ", sam=" + samMT + 168 ", bridges=" + Arrays.toString(bridgeMTs)); 169 } 170 } 171 catch (LambdaConversionException e) { 172 if (correct) { 173 throw new AssertionError("Unexpected linkage error:" + 174 " e=" + e + 175 ", impl=" + mh + 176 ", inst=" + instMT + 177 ", sam=" + samMT + 178 ", bridges=" + Arrays.toString(bridgeMTs)); 179 } 180 } 181 } 182 183 private static class ConversionTable { 184 private final Map<Class<?>, Set<Class<?>>> pairs = new HashMap<>(); 185 put(Class<?> from, Class<?> to)186 public void put(Class<?> from, Class<?> to) { 187 Set<Class<?>> set = pairs.computeIfAbsent(from, f -> new HashSet<>()); 188 set.add(to); 189 } 190 contains(Class<?> from, Class<?> to)191 public boolean contains(Class<?> from, Class<?> to) { 192 return pairs.containsKey(from) && pairs.get(from).contains(to); 193 } 194 } 195 196 private static ConversionTable conversions = new ConversionTable(); 197 static { conversions.put(char.class, int.class)198 conversions.put(char.class, int.class); conversions.put(char.class, long.class)199 conversions.put(char.class, long.class); conversions.put(char.class, float.class)200 conversions.put(char.class, float.class); conversions.put(char.class, double.class)201 conversions.put(char.class, double.class); conversions.put(char.class, Character.class)202 conversions.put(char.class, Character.class); conversions.put(char.class, Object.class)203 conversions.put(char.class, Object.class); conversions.put(Character.class, char.class)204 conversions.put(Character.class, char.class); conversions.put(Character.class, int.class)205 conversions.put(Character.class, int.class); conversions.put(Character.class, long.class)206 conversions.put(Character.class, long.class); conversions.put(Character.class, float.class)207 conversions.put(Character.class, float.class); conversions.put(Character.class, double.class)208 conversions.put(Character.class, double.class); 209 conversions.put(byte.class, short.class)210 conversions.put(byte.class, short.class); conversions.put(byte.class, int.class)211 conversions.put(byte.class, int.class); conversions.put(byte.class, long.class)212 conversions.put(byte.class, long.class); conversions.put(byte.class, float.class)213 conversions.put(byte.class, float.class); conversions.put(byte.class, double.class)214 conversions.put(byte.class, double.class); conversions.put(byte.class, Byte.class)215 conversions.put(byte.class, Byte.class); conversions.put(byte.class, Object.class)216 conversions.put(byte.class, Object.class); conversions.put(Byte.class, byte.class)217 conversions.put(Byte.class, byte.class); conversions.put(Byte.class, short.class)218 conversions.put(Byte.class, short.class); conversions.put(Byte.class, int.class)219 conversions.put(Byte.class, int.class); conversions.put(Byte.class, long.class)220 conversions.put(Byte.class, long.class); conversions.put(Byte.class, float.class)221 conversions.put(Byte.class, float.class); conversions.put(Byte.class, double.class)222 conversions.put(Byte.class, double.class); 223 conversions.put(short.class, int.class)224 conversions.put(short.class, int.class); conversions.put(short.class, long.class)225 conversions.put(short.class, long.class); conversions.put(short.class, float.class)226 conversions.put(short.class, float.class); conversions.put(short.class, double.class)227 conversions.put(short.class, double.class); conversions.put(short.class, Short.class)228 conversions.put(short.class, Short.class); conversions.put(short.class, Object.class)229 conversions.put(short.class, Object.class); conversions.put(Short.class, short.class)230 conversions.put(Short.class, short.class); conversions.put(Short.class, int.class)231 conversions.put(Short.class, int.class); conversions.put(Short.class, long.class)232 conversions.put(Short.class, long.class); conversions.put(Short.class, float.class)233 conversions.put(Short.class, float.class); conversions.put(Short.class, double.class)234 conversions.put(Short.class, double.class); 235 conversions.put(int.class, long.class)236 conversions.put(int.class, long.class); conversions.put(int.class, float.class)237 conversions.put(int.class, float.class); conversions.put(int.class, double.class)238 conversions.put(int.class, double.class); conversions.put(int.class, Integer.class)239 conversions.put(int.class, Integer.class); conversions.put(int.class, Object.class)240 conversions.put(int.class, Object.class); conversions.put(Integer.class, int.class)241 conversions.put(Integer.class, int.class); conversions.put(Integer.class, long.class)242 conversions.put(Integer.class, long.class); conversions.put(Integer.class, float.class)243 conversions.put(Integer.class, float.class); conversions.put(Integer.class, double.class)244 conversions.put(Integer.class, double.class); 245 conversions.put(long.class, float.class)246 conversions.put(long.class, float.class); conversions.put(long.class, double.class)247 conversions.put(long.class, double.class); conversions.put(long.class, Long.class)248 conversions.put(long.class, Long.class); conversions.put(long.class, Object.class)249 conversions.put(long.class, Object.class); conversions.put(Long.class, long.class)250 conversions.put(Long.class, long.class); conversions.put(Long.class, float.class)251 conversions.put(Long.class, float.class); conversions.put(Long.class, double.class)252 conversions.put(Long.class, double.class); 253 conversions.put(float.class, double.class)254 conversions.put(float.class, double.class); conversions.put(float.class, Float.class)255 conversions.put(float.class, Float.class); conversions.put(float.class, Object.class)256 conversions.put(float.class, Object.class); conversions.put(Float.class, float.class)257 conversions.put(Float.class, float.class); conversions.put(Float.class, double.class)258 conversions.put(Float.class, double.class); 259 conversions.put(double.class, Double.class)260 conversions.put(double.class, Double.class); conversions.put(double.class, Object.class)261 conversions.put(double.class, Object.class); conversions.put(Double.class, double.class)262 conversions.put(Double.class, double.class); 263 conversions.put(boolean.class, Boolean.class)264 conversions.put(boolean.class, Boolean.class); conversions.put(boolean.class, Object.class)265 conversions.put(boolean.class, Object.class); conversions.put(Boolean.class, boolean.class)266 conversions.put(Boolean.class, boolean.class); 267 } 268 269 } 270