1 /* 2 * Copyright (C) 2013 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 java.lang.reflect.InvocationHandler; 18 import java.lang.reflect.Method; 19 import java.lang.reflect.Proxy; 20 21 import dalvik.annotation.optimization.CriticalNative; 22 import dalvik.annotation.optimization.FastNative; 23 24 public class Main { main(String[] args)25 public static void main(String[] args) { 26 System.loadLibrary(args[0]); 27 testFindClassOnAttachedNativeThread(); 28 testFindFieldOnAttachedNativeThread(); 29 testReflectFieldGetFromAttachedNativeThreadNative(); 30 testCallStaticVoidMethodOnSubClass(); 31 testGetMirandaMethod(); 32 testZeroLengthByteBuffers(); 33 testByteMethod(); 34 testShortMethod(); 35 testBooleanMethod(); 36 testCharMethod(); 37 testIsAssignableFromOnPrimitiveTypes(); 38 testShallowGetCallingClassLoader(); 39 testShallowGetStackClass2(); 40 testCallNonvirtual(); 41 testNewStringObject(); 42 testRemoveLocalObject(); 43 testProxyGetMethodID(); 44 testJniCriticalSectionAndGc(); 45 testCallDefaultMethods(); 46 String lambda = "λ"; 47 testInvokeLambdaMethod(() -> { System.out.println("hi-lambda: " + lambda); }); 48 String def = "δ"; 49 testInvokeLambdaDefaultMethod(() -> { System.out.println("hi-default " + def + lambda); }); 50 51 registerNativesJniTest(); 52 testFastNativeMethods(); 53 testCriticalNativeMethods(); 54 } 55 registerNativesJniTest()56 private static native boolean registerNativesJniTest(); 57 testCallDefaultMethods()58 private static native void testCallDefaultMethods(); 59 testFindClassOnAttachedNativeThread()60 private static native void testFindClassOnAttachedNativeThread(); 61 62 private static boolean testFindFieldOnAttachedNativeThreadField; 63 testReflectFieldGetFromAttachedNativeThreadNative()64 private static native void testReflectFieldGetFromAttachedNativeThreadNative(); 65 66 public static boolean testReflectFieldGetFromAttachedNativeThreadField; 67 testFindFieldOnAttachedNativeThread()68 private static void testFindFieldOnAttachedNativeThread() { 69 testFindFieldOnAttachedNativeThreadNative(); 70 if (!testFindFieldOnAttachedNativeThreadField) { 71 throw new AssertionError(); 72 } 73 } 74 testFindFieldOnAttachedNativeThreadNative()75 private static native void testFindFieldOnAttachedNativeThreadNative(); 76 testCallStaticVoidMethodOnSubClass()77 private static void testCallStaticVoidMethodOnSubClass() { 78 testCallStaticVoidMethodOnSubClassNative(); 79 if (!testCallStaticVoidMethodOnSubClass_SuperClass.executed) { 80 throw new AssertionError(); 81 } 82 } 83 testCallStaticVoidMethodOnSubClassNative()84 private static native void testCallStaticVoidMethodOnSubClassNative(); 85 86 private static class testCallStaticVoidMethodOnSubClass_SuperClass { 87 private static boolean executed = false; execute()88 private static void execute() { 89 executed = true; 90 } 91 } 92 93 private static class testCallStaticVoidMethodOnSubClass_SubClass 94 extends testCallStaticVoidMethodOnSubClass_SuperClass { 95 } 96 testGetMirandaMethodNative()97 private static native Method testGetMirandaMethodNative(); 98 testGetMirandaMethod()99 private static void testGetMirandaMethod() { 100 Method m = testGetMirandaMethodNative(); 101 if (m.getDeclaringClass() != testGetMirandaMethod_MirandaInterface.class) { 102 throw new AssertionError(); 103 } 104 } 105 testZeroLengthByteBuffers()106 private static native void testZeroLengthByteBuffers(); 107 108 private static abstract class testGetMirandaMethod_MirandaAbstract implements testGetMirandaMethod_MirandaInterface { inAbstract()109 public boolean inAbstract() { 110 return true; 111 } 112 } 113 114 private static interface testGetMirandaMethod_MirandaInterface { inInterface()115 public boolean inInterface(); 116 } 117 118 // Test sign-extension for values < 32b 119 byteMethod(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8, byte b9, byte b10)120 static native byte byteMethod(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, 121 byte b8, byte b9, byte b10); 122 testByteMethod()123 private static void testByteMethod() { 124 byte returns[] = { 0, 1, 2, 127, -1, -2, -128 }; 125 for (int i = 0; i < returns.length; i++) { 126 byte result = byteMethod((byte)i, (byte)2, (byte)(-3), (byte)4, (byte)(-5), (byte)6, 127 (byte)(-7), (byte)8, (byte)(-9), (byte)10); 128 if (returns[i] != result) { 129 System.out.println("Run " + i + " with " + returns[i] + " vs " + result); 130 throw new AssertionError(); 131 } 132 } 133 } 134 removeLocalObject(Object o)135 private static native void removeLocalObject(Object o); 136 testRemoveLocalObject()137 private static void testRemoveLocalObject() { 138 removeLocalObject(new Object()); 139 } 140 shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7, short s8, short s9, short s10)141 private static native short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7, 142 short s8, short s9, short s10); 143 testShortMethod()144 private static void testShortMethod() { 145 short returns[] = { 0, 1, 2, 127, 32767, -1, -2, -128, -32768 }; 146 for (int i = 0; i < returns.length; i++) { 147 short result = shortMethod((short)i, (short)2, (short)(-3), (short)4, (short)(-5), (short)6, 148 (short)(-7), (short)8, (short)(-9), (short)10); 149 if (returns[i] != result) { 150 System.out.println("Run " + i + " with " + returns[i] + " vs " + result); 151 throw new AssertionError(); 152 } 153 } 154 } 155 156 // Test zero-extension for values < 32b 157 booleanMethod(boolean b1, boolean b2, boolean b3, boolean b4, boolean b5, boolean b6, boolean b7, boolean b8, boolean b9, boolean b10)158 private static native boolean booleanMethod(boolean b1, boolean b2, boolean b3, boolean b4, boolean b5, boolean b6, boolean b7, 159 boolean b8, boolean b9, boolean b10); 160 testBooleanMethod()161 private static void testBooleanMethod() { 162 if (booleanMethod(false, true, false, true, false, true, false, true, false, true)) { 163 throw new AssertionError(); 164 } 165 166 if (!booleanMethod(true, true, false, true, false, true, false, true, false, true)) { 167 throw new AssertionError(); 168 } 169 } 170 charMethod(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10)171 private static native char charMethod(char c1, char c2, char c3, char c4, char c5, char c6, char c7, 172 char c8, char c9, char c10); 173 testCharMethod()174 private static void testCharMethod() { 175 char returns[] = { (char)0, (char)1, (char)2, (char)127, (char)255, (char)256, (char)15000, 176 (char)34000 }; 177 for (int i = 0; i < returns.length; i++) { 178 char result = charMethod((char)i, 'a', 'b', 'c', '0', '1', '2', (char)1234, (char)2345, 179 (char)3456); 180 if (returns[i] != result) { 181 System.out.println("Run " + i + " with " + (int)returns[i] + " vs " + (int)result); 182 throw new AssertionError(); 183 } 184 } 185 } 186 187 // http://b/16531674 testIsAssignableFromOnPrimitiveTypes()188 private static void testIsAssignableFromOnPrimitiveTypes() { 189 if (!nativeIsAssignableFrom(int.class, Integer.TYPE)) { 190 System.out.println("IsAssignableFrom(int.class, Integer.TYPE) returned false, expected true"); 191 throw new AssertionError(); 192 } 193 194 if (!nativeIsAssignableFrom(Integer.TYPE, int.class)) { 195 System.out.println("IsAssignableFrom(Integer.TYPE, int.class) returned false, expected true"); 196 throw new AssertionError(); 197 } 198 } 199 nativeIsAssignableFrom(Class<?> from, Class<?> to)200 private static native boolean nativeIsAssignableFrom(Class<?> from, Class<?> to); 201 testShallowGetCallingClassLoader()202 private static void testShallowGetCallingClassLoader() { 203 nativeTestShallowGetCallingClassLoader(); 204 } 205 nativeTestShallowGetCallingClassLoader()206 private native static void nativeTestShallowGetCallingClassLoader(); 207 testShallowGetStackClass2()208 private static void testShallowGetStackClass2() { 209 nativeTestShallowGetStackClass2(); 210 } 211 nativeTestShallowGetStackClass2()212 private static native void nativeTestShallowGetStackClass2(); 213 testCallNonvirtual()214 private static native void testCallNonvirtual(); 215 testNewStringObject()216 private static native void testNewStringObject(); 217 218 private interface SimpleInterface { a()219 void a(); 220 } 221 222 private static class DummyInvocationHandler implements InvocationHandler { invoke(Object proxy, Method method, Object[] args)223 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 224 return null; 225 } 226 } 227 testProxyGetMethodID()228 private static void testProxyGetMethodID() { 229 InvocationHandler handler = new DummyInvocationHandler(); 230 SimpleInterface proxy = 231 (SimpleInterface) Proxy.newProxyInstance(SimpleInterface.class.getClassLoader(), 232 new Class<?>[] {SimpleInterface.class}, handler); 233 if (testGetMethodID(SimpleInterface.class) == 0) { 234 throw new AssertionError(); 235 } 236 if (testGetMethodID(proxy.getClass()) == 0) { 237 throw new AssertionError(); 238 } 239 } 240 testGetMethodID(Class<?> c)241 private static native long testGetMethodID(Class<?> c); 242 243 // Exercise GC and JNI critical sections in parallel. testJniCriticalSectionAndGc()244 private static void testJniCriticalSectionAndGc() { 245 Thread runGcThread = new Thread(new Runnable() { 246 @Override 247 public void run() { 248 for (int i = 0; i < 10; ++i) { 249 Runtime.getRuntime().gc(); 250 } 251 } 252 }); 253 Thread jniCriticalThread = new Thread(new Runnable() { 254 @Override 255 public void run() { 256 final int arraySize = 32; 257 byte[] array0 = new byte[arraySize]; 258 byte[] array1 = new byte[arraySize]; 259 enterJniCriticalSection(arraySize, array0, array1); 260 } 261 }); 262 jniCriticalThread.start(); 263 runGcThread.start(); 264 try { 265 jniCriticalThread.join(); 266 runGcThread.join(); 267 } catch (InterruptedException ignored) {} 268 } 269 enterJniCriticalSection(int arraySize, byte[] array0, byte[] array)270 private static native void enterJniCriticalSection(int arraySize, byte[] array0, byte[] array); 271 testInvokeLambdaMethod(LambdaInterface iface)272 private static native void testInvokeLambdaMethod(LambdaInterface iface); 273 testInvokeLambdaDefaultMethod(LambdaInterface iface)274 private static native void testInvokeLambdaDefaultMethod(LambdaInterface iface); 275 276 // Test invoking @FastNative methods works correctly. 277 278 // Return sum of a+b+c. 279 @FastNative intFastNativeMethod(int a, int b, int c)280 static native int intFastNativeMethod(int a, int b, int c); 281 testFastNativeMethods()282 private static void testFastNativeMethods() { 283 int returns[] = { 0, 3, 6, 9, 12 }; 284 for (int i = 0; i < returns.length; i++) { 285 int result = intFastNativeMethod(i, i, i); 286 if (returns[i] != result) { 287 System.out.println("FastNative Int Run " + i + " with " + returns[i] + " vs " + result); 288 throw new AssertionError(); 289 } 290 } 291 } 292 293 // Smoke test for @CriticalNative 294 // TODO: Way more thorough tests since it involved quite a bit of changes. 295 296 // Return sum of a+b+c. 297 @CriticalNative intCriticalNativeMethod(int a, int b, int c)298 static native int intCriticalNativeMethod(int a, int b, int c); 299 testCriticalNativeMethods()300 private static void testCriticalNativeMethods() { 301 int returns[] = { 3, 6, 9, 12, 15 }; 302 for (int i = 0; i < returns.length; i++) { 303 int result = intCriticalNativeMethod(i, i+1, i+2); 304 if (returns[i] != result) { 305 System.out.println("CriticalNative Int Run " + i + " with " + returns[i] + " vs " + result); 306 throw new AssertionError(); 307 } 308 } 309 } 310 } 311 312 @FunctionalInterface 313 interface LambdaInterface { sayHi()314 public void sayHi(); sayHiTwice()315 public default void sayHiTwice() { 316 sayHi(); 317 sayHi(); 318 } 319 } 320 321 class JniCallNonvirtualTest { 322 public boolean nonstaticMethodSuperCalled = false; 323 public boolean nonstaticMethodSubCalled = false; 324 testCallNonvirtual()325 private static native void testCallNonvirtual(); 326 JniCallNonvirtualTest()327 public JniCallNonvirtualTest() { 328 System.out.println("Super.<init>"); 329 } 330 staticMethod()331 public static void staticMethod() { 332 System.out.println("Super.staticMethod"); 333 } 334 nonstaticMethod()335 public void nonstaticMethod() { 336 System.out.println("Super.nonstaticMethod"); 337 nonstaticMethodSuperCalled = true; 338 } 339 } 340 341 class JniCallNonvirtualTestSubclass extends JniCallNonvirtualTest { 342 JniCallNonvirtualTestSubclass()343 public JniCallNonvirtualTestSubclass() { 344 System.out.println("Subclass.<init>"); 345 } 346 staticMethod()347 public static void staticMethod() { 348 System.out.println("Subclass.staticMethod"); 349 } 350 nonstaticMethod()351 public void nonstaticMethod() { 352 System.out.println("Subclass.nonstaticMethod"); 353 nonstaticMethodSubCalled = true; 354 } 355 } 356