1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandle; 18*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles; 19*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodType; 20*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.VarHandle; 21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.InvocationTargetException; 22*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker public class Main { 25*795d594fSAndroid Build Coastguard Worker private static final int ITERATIONS = 100; 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker private static final VarHandle widgetIdVarHandle; 28*795d594fSAndroid Build Coastguard Worker private static int initialHotnessCounter; 29*795d594fSAndroid Build Coastguard Worker getHotnessCounter(Class<?> cls, String methodName)30*795d594fSAndroid Build Coastguard Worker public static native int getHotnessCounter(Class<?> cls, String methodName); 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker public static class Widget { Widget(int id)33*795d594fSAndroid Build Coastguard Worker public Widget(int id) { 34*795d594fSAndroid Build Coastguard Worker this.id = id; 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker getId()37*795d594fSAndroid Build Coastguard Worker int getId() { 38*795d594fSAndroid Build Coastguard Worker return id; 39*795d594fSAndroid Build Coastguard Worker } 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker int id; 42*795d594fSAndroid Build Coastguard Worker } 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker static { 45*795d594fSAndroid Build Coastguard Worker try { 46*795d594fSAndroid Build Coastguard Worker widgetIdVarHandle = MethodHandles.lookup().findVarHandle(Widget.class, "id", int.class); 47*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 48*795d594fSAndroid Build Coastguard Worker throw new Error(e); 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker } 51*795d594fSAndroid Build Coastguard Worker assertEquals(int i1, int i2)52*795d594fSAndroid Build Coastguard Worker private static void assertEquals(int i1, int i2) { 53*795d594fSAndroid Build Coastguard Worker if (i1 == i2) { 54*795d594fSAndroid Build Coastguard Worker return; 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2); 57*795d594fSAndroid Build Coastguard Worker } 58*795d594fSAndroid Build Coastguard Worker assertEquals(Object o, Object p)59*795d594fSAndroid Build Coastguard Worker private static void assertEquals(Object o, Object p) { 60*795d594fSAndroid Build Coastguard Worker if (o == p) { 61*795d594fSAndroid Build Coastguard Worker return; 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker if (o != null && p != null && o.equals(p)) { 64*795d594fSAndroid Build Coastguard Worker return; 65*795d594fSAndroid Build Coastguard Worker } 66*795d594fSAndroid Build Coastguard Worker throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker fail()69*795d594fSAndroid Build Coastguard Worker private static void fail() { 70*795d594fSAndroid Build Coastguard Worker System.out.println("fail"); 71*795d594fSAndroid Build Coastguard Worker Thread.dumpStack(); 72*795d594fSAndroid Build Coastguard Worker } 73*795d594fSAndroid Build Coastguard Worker fail(String message)74*795d594fSAndroid Build Coastguard Worker private static void fail(String message) { 75*795d594fSAndroid Build Coastguard Worker System.out.println("fail: " + message); 76*795d594fSAndroid Build Coastguard Worker Thread.dumpStack(); 77*795d594fSAndroid Build Coastguard Worker } 78*795d594fSAndroid Build Coastguard Worker testMethodHandleCounters()79*795d594fSAndroid Build Coastguard Worker private static void testMethodHandleCounters() throws Throwable { 80*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < ITERATIONS; ++i) { 81*795d594fSAndroid Build Coastguard Worker // Regular MethodHandle invocations 82*795d594fSAndroid Build Coastguard Worker MethodHandle mh = 83*795d594fSAndroid Build Coastguard Worker MethodHandles.lookup() 84*795d594fSAndroid Build Coastguard Worker .findConstructor( 85*795d594fSAndroid Build Coastguard Worker Widget.class, MethodType.methodType(void.class, int.class)); 86*795d594fSAndroid Build Coastguard Worker Widget w = (Widget) mh.invoke(3); 87*795d594fSAndroid Build Coastguard Worker w = (Widget) mh.invokeExact(3); 88*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(MethodHandle.class, "invoke")); 89*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(MethodHandle.class, "invokeExact")); 90*795d594fSAndroid Build Coastguard Worker 91*795d594fSAndroid Build Coastguard Worker // Reflective MethodHandle invocations 92*795d594fSAndroid Build Coastguard Worker String[] methodNames = {"invoke", "invokeExact"}; 93*795d594fSAndroid Build Coastguard Worker for (String methodName : methodNames) { 94*795d594fSAndroid Build Coastguard Worker Method invokeMethod = MethodHandle.class.getMethod(methodName, Object[].class); 95*795d594fSAndroid Build Coastguard Worker MethodHandle instance = 96*795d594fSAndroid Build Coastguard Worker MethodHandles.lookup() 97*795d594fSAndroid Build Coastguard Worker .findVirtual( 98*795d594fSAndroid Build Coastguard Worker Widget.class, "getId", MethodType.methodType(int.class)); 99*795d594fSAndroid Build Coastguard Worker try { 100*795d594fSAndroid Build Coastguard Worker invokeMethod.invoke(instance, new Object[] {new Object[] {}}); 101*795d594fSAndroid Build Coastguard Worker fail(); 102*795d594fSAndroid Build Coastguard Worker } catch (InvocationTargetException ite) { 103*795d594fSAndroid Build Coastguard Worker assertEquals(ite.getCause().getClass(), UnsupportedOperationException.class); 104*795d594fSAndroid Build Coastguard Worker } 105*795d594fSAndroid Build Coastguard Worker } 106*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, 107*795d594fSAndroid Build Coastguard Worker getHotnessCounter(MethodHandle.class, "invoke")); 108*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, 109*795d594fSAndroid Build Coastguard Worker getHotnessCounter(MethodHandle.class, "invokeExact")); 110*795d594fSAndroid Build Coastguard Worker } 111*795d594fSAndroid Build Coastguard Worker 112*795d594fSAndroid Build Coastguard Worker System.out.println("MethodHandle OK"); 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker testVarHandleCounters()115*795d594fSAndroid Build Coastguard Worker private static void testVarHandleCounters() throws Throwable { 116*795d594fSAndroid Build Coastguard Worker Widget w = new Widget(0); 117*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < ITERATIONS; ++i) { 118*795d594fSAndroid Build Coastguard Worker // Regular accessor invocations 119*795d594fSAndroid Build Coastguard Worker widgetIdVarHandle.set(w, i); 120*795d594fSAndroid Build Coastguard Worker assertEquals(i, widgetIdVarHandle.get(w)); 121*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(VarHandle.class, "set")); 122*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(VarHandle.class, "get")); 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker // Reflective accessor invocations 125*795d594fSAndroid Build Coastguard Worker for (String accessorName : new String[] {"get", "set"}) { 126*795d594fSAndroid Build Coastguard Worker Method setMethod = VarHandle.class.getMethod(accessorName, Object[].class); 127*795d594fSAndroid Build Coastguard Worker try { 128*795d594fSAndroid Build Coastguard Worker setMethod.invoke(widgetIdVarHandle, new Object[] {new Object[0]}); 129*795d594fSAndroid Build Coastguard Worker fail(); 130*795d594fSAndroid Build Coastguard Worker } catch (InvocationTargetException ite) { 131*795d594fSAndroid Build Coastguard Worker assertEquals(ite.getCause().getClass(), UnsupportedOperationException.class); 132*795d594fSAndroid Build Coastguard Worker } 133*795d594fSAndroid Build Coastguard Worker } 134*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(VarHandle.class, "set")); 135*795d594fSAndroid Build Coastguard Worker assertEquals(initialHotnessCounter, getHotnessCounter(VarHandle.class, "get")); 136*795d594fSAndroid Build Coastguard Worker } 137*795d594fSAndroid Build Coastguard Worker System.out.println("VarHandle OK"); 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker main(String[] args)140*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Throwable { 141*795d594fSAndroid Build Coastguard Worker System.loadLibrary(args[0]); 142*795d594fSAndroid Build Coastguard Worker initialHotnessCounter = getHotnessCounter(VarHandle.class, "set"); 143*795d594fSAndroid Build Coastguard Worker testMethodHandleCounters(); 144*795d594fSAndroid Build Coastguard Worker testVarHandleCounters(); 145*795d594fSAndroid Build Coastguard Worker } 146*795d594fSAndroid Build Coastguard Worker } 147