• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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