xref: /aosp_15_r20/art/test/2277-methodhandle-invokeexact/src/JavaApiTest.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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