jni_test.cc revision 1c83cbc4a817acbd7f9abb5b29a2d418a958e6a1
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#include <assert.h> 18#include <stdio.h> 19#include <pthread.h> 20#include <vector> 21 22#include "jni.h" 23 24#if defined(NDEBUG) 25#error test code compiled without NDEBUG 26#endif 27 28static JavaVM* jvm = NULL; 29 30extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) { 31 assert(vm != NULL); 32 assert(jvm == NULL); 33 jvm = vm; 34 return JNI_VERSION_1_6; 35} 36 37static void* testFindClassOnAttachedNativeThread(void*) { 38 assert(jvm != NULL); 39 40 JNIEnv* env = NULL; 41 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL }; 42 int attach_result = jvm->AttachCurrentThread(&env, &args); 43 assert(attach_result == 0); 44 45 jclass clazz = env->FindClass("Main"); 46 assert(clazz != NULL); 47 assert(!env->ExceptionCheck()); 48 49 jobjectArray array = env->NewObjectArray(0, clazz, NULL); 50 assert(array != NULL); 51 assert(!env->ExceptionCheck()); 52 53 int detach_result = jvm->DetachCurrentThread(); 54 assert(detach_result == 0); 55 return NULL; 56} 57 58// http://b/10994325 59extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, 60 jclass) { 61 pthread_t pthread; 62 int pthread_create_result = pthread_create(&pthread, 63 NULL, 64 testFindClassOnAttachedNativeThread, 65 NULL); 66 assert(pthread_create_result == 0); 67 int pthread_join_result = pthread_join(pthread, NULL); 68 assert(pthread_join_result == 0); 69} 70 71static void* testFindFieldOnAttachedNativeThread(void*) { 72 assert(jvm != NULL); 73 74 JNIEnv* env = NULL; 75 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL }; 76 int attach_result = jvm->AttachCurrentThread(&env, &args); 77 assert(attach_result == 0); 78 79 jclass clazz = env->FindClass("Main"); 80 assert(clazz != NULL); 81 assert(!env->ExceptionCheck()); 82 83 jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z"); 84 assert(field != NULL); 85 assert(!env->ExceptionCheck()); 86 87 env->SetStaticBooleanField(clazz, field, JNI_TRUE); 88 89 int detach_result = jvm->DetachCurrentThread(); 90 assert(detach_result == 0); 91 return NULL; 92} 93 94extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*, 95 jclass) { 96 pthread_t pthread; 97 int pthread_create_result = pthread_create(&pthread, 98 NULL, 99 testFindFieldOnAttachedNativeThread, 100 NULL); 101 assert(pthread_create_result == 0); 102 int pthread_join_result = pthread_join(pthread, NULL); 103 assert(pthread_join_result == 0); 104} 105 106static void* testReflectFieldGetFromAttachedNativeThread(void*) { 107 assert(jvm != NULL); 108 109 JNIEnv* env = NULL; 110 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL }; 111 int attach_result = jvm->AttachCurrentThread(&env, &args); 112 assert(attach_result == 0); 113 114 jclass clazz = env->FindClass("Main"); 115 assert(clazz != NULL); 116 assert(!env->ExceptionCheck()); 117 118 jclass class_clazz = env->FindClass("java/lang/Class"); 119 assert(class_clazz != NULL); 120 assert(!env->ExceptionCheck()); 121 122 jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField", 123 "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); 124 assert(getFieldMetodId != NULL); 125 assert(!env->ExceptionCheck()); 126 127 jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField"); 128 assert(field_name != NULL); 129 assert(!env->ExceptionCheck()); 130 131 jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name); 132 assert(field != NULL); 133 assert(!env->ExceptionCheck()); 134 135 jclass field_clazz = env->FindClass("java/lang/reflect/Field"); 136 assert(field_clazz != NULL); 137 assert(!env->ExceptionCheck()); 138 139 jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean", 140 "(Ljava/lang/Object;)Z"); 141 assert(getBooleanMetodId != NULL); 142 assert(!env->ExceptionCheck()); 143 144 jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz); 145 assert(value == false); 146 assert(!env->ExceptionCheck()); 147 148 int detach_result = jvm->DetachCurrentThread(); 149 assert(detach_result == 0); 150 return NULL; 151} 152 153// http://b/15539150 154extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative( 155 JNIEnv*, jclass) { 156 pthread_t pthread; 157 int pthread_create_result = pthread_create(&pthread, 158 NULL, 159 testReflectFieldGetFromAttachedNativeThread, 160 NULL); 161 assert(pthread_create_result == 0); 162 int pthread_join_result = pthread_join(pthread, NULL); 163 assert(pthread_join_result == 0); 164} 165 166 167// http://b/11243757 168extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, 169 jclass) { 170 jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass"); 171 assert(super_class != NULL); 172 173 jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V"); 174 assert(execute != NULL); 175 176 jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass"); 177 assert(sub_class != NULL); 178 179 env->CallStaticVoidMethod(sub_class, execute); 180} 181 182extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) { 183 jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract"); 184 assert(abstract_class != NULL); 185 jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z"); 186 assert(miranda_method != NULL); 187 return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE); 188} 189 190// https://code.google.com/p/android/issues/detail?id=63055 191extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) { 192 std::vector<uint8_t> buffer(1); 193 jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0); 194 assert(byte_buffer != NULL); 195 assert(!env->ExceptionCheck()); 196 197 assert(env->GetDirectBufferAddress(byte_buffer) == &buffer[0]); 198 assert(env->GetDirectBufferCapacity(byte_buffer) == 0); 199} 200 201constexpr size_t kByteReturnSize = 7; 202jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 }; 203 204extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv* env, jclass klass, jbyte b1, jbyte b2, 205 jbyte b3, jbyte b4, jbyte b5, jbyte b6, 206 jbyte b7, jbyte b8, jbyte b9, jbyte b10) { 207 // We use b1 to drive the output. 208 assert(b2 == 2); 209 assert(b3 == -3); 210 assert(b4 == 4); 211 assert(b5 == -5); 212 assert(b6 == 6); 213 assert(b7 == -7); 214 assert(b8 == 8); 215 assert(b9 == -9); 216 assert(b10 == 10); 217 218 assert(0 <= b1); 219 assert(b1 < static_cast<jbyte>(kByteReturnSize)); 220 221 return byte_returns[b1]; 222} 223 224constexpr size_t kShortReturnSize = 9; 225jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128, 226 static_cast<jshort>(0x8000) }; 227// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768. 228 229extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv* env, jclass klass, jshort s1, jshort s2, 230 jshort s3, jshort s4, jshort s5, jshort s6, 231 jshort s7, jshort s8, jshort s9, jshort s10) { 232 // We use s1 to drive the output. 233 assert(s2 == 2); 234 assert(s3 == -3); 235 assert(s4 == 4); 236 assert(s5 == -5); 237 assert(s6 == 6); 238 assert(s7 == -7); 239 assert(s8 == 8); 240 assert(s9 == -9); 241 assert(s10 == 10); 242 243 assert(0 <= s1); 244 assert(s1 < static_cast<jshort>(kShortReturnSize)); 245 246 return short_returns[s1]; 247} 248 249extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv* env, jclass klass, jboolean b1, 250 jboolean b2, jboolean b3, jboolean b4, 251 jboolean b5, jboolean b6, jboolean b7, 252 jboolean b8, jboolean b9, jboolean b10) { 253 // We use b1 to drive the output. 254 assert(b2 == JNI_TRUE); 255 assert(b3 == JNI_FALSE); 256 assert(b4 == JNI_TRUE); 257 assert(b5 == JNI_FALSE); 258 assert(b6 == JNI_TRUE); 259 assert(b7 == JNI_FALSE); 260 assert(b8 == JNI_TRUE); 261 assert(b9 == JNI_FALSE); 262 assert(b10 == JNI_TRUE); 263 264 assert(b1 == JNI_TRUE || b1 == JNI_FALSE); 265 return b1; 266} 267 268constexpr size_t kCharReturnSize = 8; 269jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 }; 270 271extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv* env, jclass klacc, jchar c1, jchar c2, 272 jchar c3, jchar c4, jchar c5, jchar c6, 273 jchar c7, jchar c8, jchar c9, jchar c10) { 274 // We use c1 to drive the output. 275 assert(c2 == 'a'); 276 assert(c3 == 'b'); 277 assert(c4 == 'c'); 278 assert(c5 == '0'); 279 assert(c6 == '1'); 280 assert(c7 == '2'); 281 assert(c8 == 1234); 282 assert(c9 == 2345); 283 assert(c10 == 3456); 284 285 assert(c1 < static_cast<jchar>(kCharReturnSize)); 286 287 return char_returns[c1]; 288} 289