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