1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import static java.lang.invoke.MethodType.methodType; 18 19 import java.lang.invoke.MethodHandle; 20 import java.lang.invoke.MethodHandles; 21 import java.util.Arrays; 22 import java.util.Optional; 23 24 public class JavaApiTest extends AbstractInvokeExactTest { 25 26 private static final MethodHandle OPTIONAL_GET; 27 28 private static final MethodHandle VOID_METHOD; 29 private static final MethodHandle RETURN_INT; 30 private static final MethodHandle RETURN_DOUBLE; 31 private static final MethodHandle PRIVATE_INTERFACE_METHOD; 32 private static final MethodHandle B_PRIVATE_RETURN_INT; 33 private static final MethodHandle A_PRIVATE_RETURN_INT; 34 private static final MethodHandle STATIC_METHOD; 35 private static final MethodHandle EXCEPTION_THROWING_METHOD; 36 private static final MethodHandle INTERFACE_DEFAULT_METHOD; 37 private static final MethodHandle OVERWRITTEN_INTERFACE_DEFAULT_METHOD; 38 39 private static final MethodHandle SUM_I; 40 private static final MethodHandle SUM_2I; 41 private static final MethodHandle SUM_3I; 42 private static final MethodHandle SUM_4I; 43 private static final MethodHandle SUM_5I; 44 private static final MethodHandle SUM_6I; 45 private static final MethodHandle SUM_7I; 46 private static final MethodHandle SUM_8I; 47 private static final MethodHandle SUM_9I; 48 private static final MethodHandle SUM_10I; 49 50 private static final MethodHandle SUM_IJ; 51 private static final MethodHandle SUM_2IJ; 52 private static final MethodHandle SUM_3IJ; 53 private static final MethodHandle SUM_4IJ; 54 private static final MethodHandle SUM_5IJ; 55 56 private static final MethodHandle FOO_NONDEFAULT; 57 private static final MethodHandle FOOBARIMPL_NONDEFAULT; 58 private static final MethodHandle FOO_DEFAULT; 59 private static final MethodHandle BAR_DEFAULT; 60 private static final MethodHandle FOOBAR_DEFINEDINABSTRACT; 61 private static final MethodHandle FOOBAR_NONDEFAULT; 62 private static final MethodHandle FOOBARIMPL_DEFINEDINABSTRACT; 63 private static final MethodHandle FOOBARIMPL_DEFAULT; 64 private static final MethodHandle FOO_NONOVERRIDDEN_DEFAULT; 65 private static final MethodHandle BAR_NONOVERRIDDEN_DEFAULT; 66 private static final MethodHandle TO_STRING_DEFINED_IN_AN_INTERFACE; 67 68 private static final MethodHandle INTERFACE_ONE_METHOD; 69 private static final MethodHandle INTERFACE_TWO_METHOD; 70 private static final MethodHandle INTERFACE_THREE_METHOD; 71 private static final MethodHandle INTERFACE_FOUR_METHOD; 72 private static final MethodHandle FOO_AND_FOO_CONFLICT_DEFAULT; 73 private static final MethodHandle BASE_INTERFACE; 74 75 static { 76 try { 77 OPTIONAL_GET = MethodHandles.lookup() 78 .findVirtual(Optional.class, "get", methodType(Object.class)); 79 80 VOID_METHOD = MethodHandles.lookup() 81 .findVirtual(A.class, "voidMethod", methodType(void.class)); 82 RETURN_DOUBLE = MethodHandles.lookup() 83 .findVirtual(A.class, "returnDouble", methodType(double.class)); 84 RETURN_INT = MethodHandles.lookup() 85 .findVirtual(A.class, "returnInt", methodType(int.class)); 86 PRIVATE_INTERFACE_METHOD = MethodHandles.privateLookupIn(I.class, MethodHandles.lookup()) 87 .findVirtual(I.class, "innerPrivateMethod", methodType(String.class)); 88 A_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(A.class, MethodHandles.lookup()) 89 .findVirtual(A.class, "privateReturnInt", methodType(int.class)); 90 B_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(B.class, MethodHandles.lookup()) 91 .findVirtual(B.class, "privateReturnInt", methodType(int.class)); 92 STATIC_METHOD = MethodHandles.lookup() 93 .findStatic(A.class, "staticMethod", methodType(String.class, A.class)); 94 EXCEPTION_THROWING_METHOD = MethodHandles.lookup() 95 .findVirtual(A.class, "throwException", methodType(void.class)); 96 INTERFACE_DEFAULT_METHOD = MethodHandles.lookup() 97 .findVirtual(I.class, "defaultMethod", methodType(void.class)); 98 OVERWRITTEN_INTERFACE_DEFAULT_METHOD = MethodHandles.lookup() 99 .findVirtual(I.class, "overrideMe", methodType(void.class)); 100 101 SUM_I = MethodHandles.lookup() 102 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(1, int.class))); 103 SUM_2I = MethodHandles.lookup() 104 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(2, int.class))); 105 SUM_3I = MethodHandles.lookup() 106 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(3, int.class))); 107 SUM_4I = MethodHandles.lookup() 108 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(4, int.class))); 109 SUM_5I = MethodHandles.lookup() 110 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(5, int.class))); 111 SUM_6I = MethodHandles.lookup() 112 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(6, int.class))); 113 SUM_7I = MethodHandles.lookup() 114 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(7, int.class))); 115 SUM_8I = MethodHandles.lookup() 116 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(8, int.class))); 117 SUM_9I = MethodHandles.lookup() 118 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(9, int.class))); 119 SUM_10I = MethodHandles.lookup() 120 .findVirtual(Sums.class, "sum", methodType(int.class, repeat(10, int.class))); 121 122 SUM_IJ = MethodHandles.lookup() 123 .findVirtual(Sums.class, "sum", methodType(long.class, int.class, long.class)); 124 SUM_2IJ = MethodHandles.lookup() 125 .findVirtual(Sums.class, 126 "sum", 127 methodType(long.class, repeat(2, int.class, long.class))); 128 SUM_3IJ = MethodHandles.lookup() 129 .findVirtual(Sums.class, 130 "sum", 131 methodType(long.class, repeat(3, int.class, long.class))); 132 SUM_4IJ = MethodHandles.lookup() 133 .findVirtual(Sums.class, 134 "sum", 135 methodType(long.class, repeat(4, int.class, long.class))); 136 SUM_5IJ = MethodHandles.lookup() 137 .findVirtual(Sums.class, 138 "sum", 139 methodType(long.class, repeat(5, int.class, long.class))); 140 141 FOO_NONDEFAULT = MethodHandles.lookup() 142 .findVirtual(Foo.class, "nonDefault", methodType(String.class)); 143 FOOBARIMPL_NONDEFAULT = MethodHandles.lookup() 144 .findVirtual(FooBarImpl.class, "nonDefault", methodType(String.class)); 145 FOO_DEFAULT = MethodHandles.lookup() 146 .findVirtual(Foo.class, "defaultToOverride", methodType(String.class)); 147 BAR_DEFAULT = MethodHandles.lookup() 148 .findVirtual(Bar.class, "defaultToOverride", methodType(String.class)); 149 FOOBAR_DEFINEDINABSTRACT = MethodHandles.lookup() 150 .findVirtual(FooBar.class, "definedInAbstract", methodType(String.class)); 151 FOOBAR_NONDEFAULT = MethodHandles.lookup() 152 .findVirtual(FooBar.class, "nonDefault", methodType(String.class)); 153 FOOBARIMPL_DEFINEDINABSTRACT = MethodHandles.lookup() 154 .findVirtual(FooBarImpl.class, "definedInAbstract", methodType(String.class)); 155 FOOBARIMPL_DEFAULT = MethodHandles.lookup() 156 .findVirtual(FooBarImpl.class, "defaultToOverride", methodType(String.class)); 157 FOO_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup() 158 .findVirtual(Foo.class, "nonOverriddenDefault", methodType(String.class)); 159 BAR_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup() 160 .findVirtual(Bar.class, "nonOverriddenDefault", methodType(String.class)); 161 TO_STRING_DEFINED_IN_AN_INTERFACE = MethodHandles.lookup() 162 .findVirtual(ToStringable.class, "toString", methodType(String.class)); 163 164 INTERFACE_ONE_METHOD = MethodHandles.lookup() 165 .findVirtual(Interface1.class, "methodOne", methodType(String.class)); 166 INTERFACE_TWO_METHOD = MethodHandles.lookup() 167 .findVirtual(Interface2.class, "methodTwo", methodType(String.class)); 168 INTERFACE_THREE_METHOD = MethodHandles.lookup() 169 .findVirtual(Interface3.class, "methodThree", methodType(String.class)); 170 INTERFACE_FOUR_METHOD = MethodHandles.lookup() 171 .findVirtual(Interface4.class, "methodFour", methodType(String.class)); 172 FOO_AND_FOO_CONFLICT_DEFAULT = MethodHandles.lookup() 173 .findVirtual(FooAndFooConflict.class, "defaultToOverride", methodType(String.class)); 174 BASE_INTERFACE = MethodHandles.lookup() 175 .findVirtual(BaseInterface.class, "method", methodType(String.class)); 176 } catch (Exception e) { 177 throw new RuntimeException(e); 178 } 179 } 180 repeat(int times, Class<?> clazz)181 private static Class<?>[] repeat(int times, Class<?> clazz) { 182 Class<?>[] classes = new Class<?>[times]; 183 Arrays.fill(classes, clazz); 184 return classes; 185 } 186 repeat(int times, Class<?> first, Class<?> second)187 private static Class<?>[] repeat(int times, Class<?> first, Class<?> second) { 188 Class<?>[] classes = new Class<?>[times * 2]; 189 for (int i = 0; i < 2 * times;) { 190 classes[i++] = first; 191 classes[i++] = second; 192 } 193 return classes; 194 } 195 196 @Override $noinline$privateMethods()197 void $noinline$privateMethods() throws Throwable { 198 assertEquals("boo", (String) PRIVATE_INTERFACE_METHOD.invokeExact((I) new A())); 199 200 int privateIntA = (int) A_PRIVATE_RETURN_INT.invokeExact(new A()); 201 assertEquals(1042, privateIntA); 202 203 int privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact(new B()); 204 assertEquals(9999, privateIntB); 205 206 privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact((B) new A()); 207 assertEquals(9999, privateIntB); 208 } 209 210 @Override voidMethod()211 public MethodHandle voidMethod() { 212 return VOID_METHOD; 213 } 214 215 @Override returnDouble()216 public MethodHandle returnDouble() { 217 return RETURN_DOUBLE; 218 } 219 220 @Override returnInt()221 public MethodHandle returnInt() { 222 return RETURN_INT; 223 } 224 225 @Override interfaceDefaultMethod()226 public MethodHandle interfaceDefaultMethod() { 227 return INTERFACE_DEFAULT_METHOD; 228 } 229 230 @Override overwrittenInterfaceDefaultMethod()231 public MethodHandle overwrittenInterfaceDefaultMethod() { 232 return OVERWRITTEN_INTERFACE_DEFAULT_METHOD; 233 } 234 235 @Override exceptionThrowingMethod()236 public MethodHandle exceptionThrowingMethod() { 237 return EXCEPTION_THROWING_METHOD; 238 } 239 240 @Override staticMethod()241 public MethodHandle staticMethod() { 242 return STATIC_METHOD; 243 } 244 245 @Override sumI()246 public MethodHandle sumI() { 247 return SUM_I; 248 } 249 250 @Override sum2I()251 public MethodHandle sum2I() { 252 return SUM_2I; 253 } 254 255 @Override sum3I()256 public MethodHandle sum3I() { 257 return SUM_3I; 258 } 259 260 @Override sum4I()261 public MethodHandle sum4I() { 262 return SUM_4I; 263 } 264 265 @Override sum5I()266 public MethodHandle sum5I() { 267 return SUM_5I; 268 } 269 270 @Override sum6I()271 public MethodHandle sum6I() { 272 return SUM_6I; 273 } 274 275 @Override sum7I()276 public MethodHandle sum7I() { 277 return SUM_7I; 278 } 279 280 @Override sum8I()281 public MethodHandle sum8I() { 282 return SUM_8I; 283 } 284 285 @Override sum9I()286 public MethodHandle sum9I() { 287 return SUM_9I; 288 } 289 290 @Override sum10I()291 public MethodHandle sum10I() { 292 return SUM_10I; 293 } 294 295 @Override sumIJ()296 public MethodHandle sumIJ() { 297 return SUM_IJ; 298 } 299 300 @Override sum2IJ()301 public MethodHandle sum2IJ() { 302 return SUM_2IJ; 303 } 304 305 @Override sum3IJ()306 public MethodHandle sum3IJ() { 307 return SUM_3IJ; 308 } 309 310 @Override sum4IJ()311 public MethodHandle sum4IJ() { 312 return SUM_4IJ; 313 } 314 315 @Override sum5IJ()316 public MethodHandle sum5IJ() { 317 return SUM_5IJ; 318 } 319 320 @Override fooNonDefault()321 public MethodHandle fooNonDefault() { 322 return FOO_NONDEFAULT; 323 } 324 325 @Override fooBarImplNonDefault()326 public MethodHandle fooBarImplNonDefault() { 327 return FOOBARIMPL_NONDEFAULT; 328 } 329 330 @Override barDefault()331 public MethodHandle barDefault() { 332 return BAR_DEFAULT; 333 } 334 335 @Override fooDefault()336 public MethodHandle fooDefault() { 337 return FOO_DEFAULT; 338 } 339 340 @Override fooBarImplDefault()341 public MethodHandle fooBarImplDefault() { 342 return FOOBARIMPL_DEFAULT; 343 } 344 345 @Override fooNonOverriddenDefault()346 public MethodHandle fooNonOverriddenDefault() { 347 return FOO_NONOVERRIDDEN_DEFAULT; 348 } 349 350 @Override barNonOverriddenDefault()351 public MethodHandle barNonOverriddenDefault() { 352 return BAR_NONOVERRIDDEN_DEFAULT; 353 } 354 355 @Override fooBarDefinedInAbstract()356 public MethodHandle fooBarDefinedInAbstract() { 357 return FOOBAR_DEFINEDINABSTRACT; 358 } 359 360 @Override fooBarImplDefinedInAbstract()361 public MethodHandle fooBarImplDefinedInAbstract() { 362 return FOOBARIMPL_DEFINEDINABSTRACT; 363 } 364 365 @Override fooBarNonDefault()366 public MethodHandle fooBarNonDefault() { 367 return FOOBAR_NONDEFAULT; 368 } 369 370 @Override toStringDefinedInAnInterface()371 public MethodHandle toStringDefinedInAnInterface() { 372 return TO_STRING_DEFINED_IN_AN_INTERFACE; 373 } 374 375 @Override optionalGet()376 public MethodHandle optionalGet() { 377 return OPTIONAL_GET; 378 } 379 380 @Override interfaceOneMethod()381 public MethodHandle interfaceOneMethod() { 382 return INTERFACE_ONE_METHOD; 383 } 384 385 @Override interfaceTwoMethod()386 public MethodHandle interfaceTwoMethod() { 387 return INTERFACE_TWO_METHOD; 388 } 389 390 @Override interfaceThreeMethod()391 public MethodHandle interfaceThreeMethod() { 392 return INTERFACE_THREE_METHOD; 393 } 394 395 @Override interfaceFourMethod()396 public MethodHandle interfaceFourMethod() { 397 return INTERFACE_FOUR_METHOD; 398 } 399 400 @Override fooAndFooConflictDefault()401 public MethodHandle fooAndFooConflictDefault() { 402 return FOO_AND_FOO_CONFLICT_DEFAULT; 403 } 404 405 @Override baseInterface()406 public MethodHandle baseInterface() { 407 return BASE_INTERFACE; 408 } 409 } 410