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