blob: 370bd6ad2bb0db2397dcae8271cc8a9541ed5cbc [file] [log] [blame]
Brian Carlstromce888532013-10-10 00:32:58 -07001/*
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>
Mathieu Chartier598302a2015-09-23 14:52:39 -070018#include <iostream>
Brian Carlstromce888532013-10-10 00:32:58 -070019#include <pthread.h>
Mathieu Chartier598302a2015-09-23 14:52:39 -070020#include <stdio.h>
Narayan Kamathef809d02013-12-19 17:52:47 +000021#include <vector>
Brian Carlstromce888532013-10-10 00:32:58 -070022
23#include "jni.h"
24
25#if defined(NDEBUG)
26#error test code compiled without NDEBUG
27#endif
28
Mathieu Chartier2cebb242015-04-21 16:50:40 -070029static JavaVM* jvm = nullptr;
Brian Carlstromce888532013-10-10 00:32:58 -070030
31extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
Andreas Gampe718ac652014-08-11 18:51:53 -070032 assert(vm != nullptr);
33 assert(jvm == nullptr);
Brian Carlstromce888532013-10-10 00:32:58 -070034 jvm = vm;
Mathieu Chartier598302a2015-09-23 14:52:39 -070035 std::cout << "JNI_OnLoad called" << std::endl;
Brian Carlstromce888532013-10-10 00:32:58 -070036 return JNI_VERSION_1_6;
37}
38
Andreas Gampe718ac652014-08-11 18:51:53 -070039static void* AttachHelper(void* arg) {
40 assert(jvm != nullptr);
Brian Carlstromce888532013-10-10 00:32:58 -070041
Andreas Gampe718ac652014-08-11 18:51:53 -070042 JNIEnv* env = nullptr;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070043 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr };
Brian Carlstromce888532013-10-10 00:32:58 -070044 int attach_result = jvm->AttachCurrentThread(&env, &args);
45 assert(attach_result == 0);
46
Andreas Gampe718ac652014-08-11 18:51:53 -070047 typedef void (*Fn)(JNIEnv*);
48 Fn fn = reinterpret_cast<Fn>(arg);
49 fn(env);
Brian Carlstromce888532013-10-10 00:32:58 -070050
51 int detach_result = jvm->DetachCurrentThread();
52 assert(detach_result == 0);
Andreas Gampe718ac652014-08-11 18:51:53 -070053 return nullptr;
54}
55
56static void PthreadHelper(void (*fn)(JNIEnv*)) {
57 pthread_t pthread;
58 int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
59 reinterpret_cast<void*>(fn));
60 assert(pthread_create_result == 0);
61 int pthread_join_result = pthread_join(pthread, nullptr);
62 assert(pthread_join_result == 0);
63}
64
65static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
66 jclass clazz = env->FindClass("Main");
67 assert(clazz != nullptr);
68 assert(!env->ExceptionCheck());
69
70 jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
71 assert(array != nullptr);
72 assert(!env->ExceptionCheck());
Brian Carlstromce888532013-10-10 00:32:58 -070073}
74
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070075// http://b/10994325
Andreas Gampe718ac652014-08-11 18:51:53 -070076extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) {
77 PthreadHelper(&testFindClassOnAttachedNativeThread);
Brian Carlstromce888532013-10-10 00:32:58 -070078}
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070079
Andreas Gampe718ac652014-08-11 18:51:53 -070080static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070081 jclass clazz = env->FindClass("Main");
Andreas Gampe718ac652014-08-11 18:51:53 -070082 assert(clazz != nullptr);
Jeff Hao62509b62013-12-10 17:44:56 -080083 assert(!env->ExceptionCheck());
84
85 jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z");
Andreas Gampe718ac652014-08-11 18:51:53 -070086 assert(field != nullptr);
Jeff Hao62509b62013-12-10 17:44:56 -080087 assert(!env->ExceptionCheck());
88
89 env->SetStaticBooleanField(clazz, field, JNI_TRUE);
Jeff Hao62509b62013-12-10 17:44:56 -080090}
91
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070092extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -070093 jclass) {
94 PthreadHelper(&testFindFieldOnAttachedNativeThread);
Jeff Hao62509b62013-12-10 17:44:56 -080095}
96
Andreas Gampe718ac652014-08-11 18:51:53 -070097static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070098 jclass clazz = env->FindClass("Main");
Andreas Gampe718ac652014-08-11 18:51:53 -070099 assert(clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100100 assert(!env->ExceptionCheck());
101
102 jclass class_clazz = env->FindClass("java/lang/Class");
Andreas Gampe718ac652014-08-11 18:51:53 -0700103 assert(class_clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100104 assert(!env->ExceptionCheck());
105
106 jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
107 "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
Andreas Gampe718ac652014-08-11 18:51:53 -0700108 assert(getFieldMetodId != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100109 assert(!env->ExceptionCheck());
110
111 jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
Andreas Gampe718ac652014-08-11 18:51:53 -0700112 assert(field_name != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100113 assert(!env->ExceptionCheck());
114
115 jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
Andreas Gampe718ac652014-08-11 18:51:53 -0700116 assert(field != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100117 assert(!env->ExceptionCheck());
118
119 jclass field_clazz = env->FindClass("java/lang/reflect/Field");
Andreas Gampe718ac652014-08-11 18:51:53 -0700120 assert(field_clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100121 assert(!env->ExceptionCheck());
122
123 jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
124 "(Ljava/lang/Object;)Z");
Andreas Gampe718ac652014-08-11 18:51:53 -0700125 assert(getBooleanMetodId != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100126 assert(!env->ExceptionCheck());
127
128 jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
129 assert(value == false);
130 assert(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100131}
132
133// http://b/15539150
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700134extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100135 JNIEnv*, jclass) {
Andreas Gampe718ac652014-08-11 18:51:53 -0700136 PthreadHelper(&testReflectFieldGetFromAttachedNativeThread);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100137}
138
Jeff Hao62509b62013-12-10 17:44:56 -0800139
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700140// http://b/11243757
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700141extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
Andreas Gampe718ac652014-08-11 18:51:53 -0700142 jclass) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700143 jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
Andreas Gampe718ac652014-08-11 18:51:53 -0700144 assert(super_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700145
146 jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V");
Andreas Gampe718ac652014-08-11 18:51:53 -0700147 assert(execute != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700148
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700149 jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
Andreas Gampe718ac652014-08-11 18:51:53 -0700150 assert(sub_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700151
152 env->CallStaticVoidMethod(sub_class, execute);
153}
Jeff Hao201803f2013-11-20 18:11:39 -0800154
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700155extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
156 jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
Andreas Gampe718ac652014-08-11 18:51:53 -0700157 assert(abstract_class != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800158 jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z");
Andreas Gampe718ac652014-08-11 18:51:53 -0700159 assert(miranda_method != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800160 return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
161}
Narayan Kamathef809d02013-12-19 17:52:47 +0000162
163// https://code.google.com/p/android/issues/detail?id=63055
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700164extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
Narayan Kamathef809d02013-12-19 17:52:47 +0000165 std::vector<uint8_t> buffer(1);
166 jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
Andreas Gampe718ac652014-08-11 18:51:53 -0700167 assert(byte_buffer != nullptr);
Narayan Kamathef809d02013-12-19 17:52:47 +0000168 assert(!env->ExceptionCheck());
169
170 assert(env->GetDirectBufferAddress(byte_buffer) == &buffer[0]);
171 assert(env->GetDirectBufferCapacity(byte_buffer) == 0);
172}
Andreas Gamped1104322014-05-01 14:38:56 -0700173
174constexpr size_t kByteReturnSize = 7;
175jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 };
176
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700177extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700178 jbyte b3, jbyte b4, jbyte b5, jbyte b6,
179 jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700180 // We use b1 to drive the output.
181 assert(b2 == 2);
182 assert(b3 == -3);
183 assert(b4 == 4);
184 assert(b5 == -5);
185 assert(b6 == 6);
186 assert(b7 == -7);
187 assert(b8 == 8);
188 assert(b9 == -9);
189 assert(b10 == 10);
190
191 assert(0 <= b1);
192 assert(b1 < static_cast<jbyte>(kByteReturnSize));
193
194 return byte_returns[b1];
195}
196
197constexpr size_t kShortReturnSize = 9;
198jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128,
199 static_cast<jshort>(0x8000) };
200// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768.
201
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700202extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jshort s2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700203 jshort s3, jshort s4, jshort s5, jshort s6,
204 jshort s7, jshort s8, jshort s9, jshort s10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700205 // We use s1 to drive the output.
206 assert(s2 == 2);
207 assert(s3 == -3);
208 assert(s4 == 4);
209 assert(s5 == -5);
210 assert(s6 == 6);
211 assert(s7 == -7);
212 assert(s8 == 8);
213 assert(s9 == -9);
214 assert(s10 == 10);
215
216 assert(0 <= s1);
217 assert(s1 < static_cast<jshort>(kShortReturnSize));
218
219 return short_returns[s1];
220}
221
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700222extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1,
Andreas Gampe718ac652014-08-11 18:51:53 -0700223 jboolean b2, jboolean b3, jboolean b4,
224 jboolean b5, jboolean b6, jboolean b7,
225 jboolean b8, jboolean b9, jboolean b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700226 // We use b1 to drive the output.
227 assert(b2 == JNI_TRUE);
228 assert(b3 == JNI_FALSE);
229 assert(b4 == JNI_TRUE);
230 assert(b5 == JNI_FALSE);
231 assert(b6 == JNI_TRUE);
232 assert(b7 == JNI_FALSE);
233 assert(b8 == JNI_TRUE);
234 assert(b9 == JNI_FALSE);
235 assert(b10 == JNI_TRUE);
236
237 assert(b1 == JNI_TRUE || b1 == JNI_FALSE);
238 return b1;
239}
240
241constexpr size_t kCharReturnSize = 8;
242jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 };
243
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700244extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700245 jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
246 jchar c8, jchar c9, jchar c10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700247 // We use c1 to drive the output.
248 assert(c2 == 'a');
249 assert(c3 == 'b');
250 assert(c4 == 'c');
251 assert(c5 == '0');
252 assert(c6 == '1');
253 assert(c7 == '2');
254 assert(c8 == 1234);
255 assert(c9 == 2345);
256 assert(c10 == 3456);
257
258 assert(c1 < static_cast<jchar>(kCharReturnSize));
259
260 return char_returns[c1];
261}
Narayan Kamath1268b742014-07-11 19:15:11 +0100262
Mathieu Chartier22c1caa2015-06-02 13:40:12 -0700263extern "C" JNIEXPORT void JNICALL Java_Main_removeLocalObject(JNIEnv* env, jclass, jclass o) {
264 // Delete the arg to see if it crashes.
265 env->DeleteLocalRef(o);
266}
267
Narayan Kamath1268b742014-07-11 19:15:11 +0100268extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* env, jclass,
269 jclass from, jclass to) {
270 return env->IsAssignableFrom(from, to);
271}
Andreas Gampe718ac652014-08-11 18:51:53 -0700272
273static void testShallowGetCallingClassLoader(JNIEnv* env) {
274 // Test direct call.
275 {
276 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
277 assert(vmstack_clazz != nullptr);
278 assert(!env->ExceptionCheck());
279
280 jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
281 "getCallingClassLoader",
282 "()Ljava/lang/ClassLoader;");
283 assert(getCallingClassLoaderMethodId != nullptr);
284 assert(!env->ExceptionCheck());
285
286 jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
287 getCallingClassLoaderMethodId);
288 assert(class_loader == nullptr);
289 assert(!env->ExceptionCheck());
290 }
291
292 // Test one-level call. Use System.loadLibrary().
293 {
294 jclass system_clazz = env->FindClass("java/lang/System");
295 assert(system_clazz != nullptr);
296 assert(!env->ExceptionCheck());
297
298 jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
299 "(Ljava/lang/String;)V");
300 assert(loadLibraryMethodId != nullptr);
301 assert(!env->ExceptionCheck());
302
303 // Create a string object.
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000304 jobject library_string = env->NewStringUTF("non_existing_library");
Andreas Gampe718ac652014-08-11 18:51:53 -0700305 assert(library_string != nullptr);
306 assert(!env->ExceptionCheck());
307
308 env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000309 assert(env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700310
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000311 // We expect UnsatisfiedLinkError.
312 jthrowable thrown = env->ExceptionOccurred();
313 env->ExceptionClear();
314
315 jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
316 jclass thrown_class = env->GetObjectClass(thrown);
317 assert(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
Andreas Gampe718ac652014-08-11 18:51:53 -0700318 }
319}
320
321// http://b/16867274
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700322extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -0700323 jclass) {
324 PthreadHelper(&testShallowGetCallingClassLoader);
325}
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700326
327static void testShallowGetStackClass2(JNIEnv* env) {
328 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
329 assert(vmstack_clazz != nullptr);
330 assert(!env->ExceptionCheck());
331
332 // Test direct call.
333 {
334 jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2",
335 "()Ljava/lang/Class;");
336 assert(getStackClass2MethodId != nullptr);
337 assert(!env->ExceptionCheck());
338
339 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId);
340 assert(caller_class == nullptr);
341 assert(!env->ExceptionCheck());
342 }
343
344 // Test one-level call. Use VMStack.getStackClass1().
345 {
346 jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1",
347 "()Ljava/lang/Class;");
348 assert(getStackClass1MethodId != nullptr);
349 assert(!env->ExceptionCheck());
350
351 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId);
352 assert(caller_class == nullptr);
353 assert(!env->ExceptionCheck());
354 }
355
356 // For better testing we would need to compile against libcore and have a two-deep stack
357 // ourselves.
358}
359
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700360extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetStackClass2(JNIEnv*, jclass) {
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700361 PthreadHelper(&testShallowGetStackClass2);
362}
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700363
364class JniCallNonvirtualVoidMethodTest {
365 public:
366 explicit JniCallNonvirtualVoidMethodTest(JNIEnv* env)
367 : env_(env),
368 check_jni_ri_(true),
369 check_jni_android_(true),
370 super_(GetClass("JniCallNonvirtualTest")),
371 sub_(GetClass("JniCallNonvirtualTestSubclass")),
372 super_constructor_(GetMethodID(super_, true, "<init>")),
373 super_static_(GetMethodID(super_, false, "staticMethod")),
374 super_nonstatic_(GetMethodID(super_, true, "nonstaticMethod")),
375 sub_constructor_(GetMethodID(sub_, true, "<init>")),
376 sub_static_(GetMethodID(sub_, false, "staticMethod")),
377 sub_nonstatic_(GetMethodID(sub_, true, "nonstaticMethod")),
378 super_field_(GetFieldID(super_, "nonstaticMethodSuperCalled")),
379 sub_field_(GetFieldID(super_, "nonstaticMethodSubCalled")) {}
380
381 void Test() {
382 TestStaticCallNonvirtualMethod();
383 TestNewObject();
384 TestnonstaticCallNonvirtualMethod();
385 }
386
387 JNIEnv* const env_;
388
389 bool const check_jni_ri_;
390 bool const check_jni_android_;
391
392 jclass const super_;
393 jclass const sub_;
394
395 jmethodID const super_constructor_;
396 jmethodID const super_static_;
397 jmethodID const super_nonstatic_;
398 jmethodID const sub_constructor_;
399 jmethodID const sub_static_;
400 jmethodID const sub_nonstatic_;
401
402 jfieldID const super_field_;
403 jfieldID const sub_field_;
404
405 private:
406 jclass GetClass(const char* class_name) {
407 jclass c = env_->FindClass(class_name);
408 if (env_->ExceptionCheck()) {
409 env_->ExceptionDescribe();
410 env_->FatalError(__FUNCTION__);
411 }
412 assert(!env_->ExceptionCheck());
413 assert(c != nullptr);
414 return c;
415 }
416
417 jmethodID GetMethodID(jclass c, bool nonstatic, const char* method_name) {
418 jmethodID m = ((nonstatic) ?
419 env_->GetMethodID(c, method_name, "()V") :
420 env_->GetStaticMethodID(c, method_name, "()V"));
421 if (env_->ExceptionCheck()) {
422 env_->ExceptionDescribe();
423 env_->FatalError(__FUNCTION__);
424 }
425 assert(m != nullptr);
426 return m;
427 }
428
429 jobject CallConstructor(jclass c, jmethodID m) {
430 jobject o = env_->NewObject(c, m);
431 if (env_->ExceptionCheck()) {
432 env_->ExceptionDescribe();
433 env_->FatalError(__FUNCTION__);
434 }
435 assert(o != nullptr);
436 return o;
437 }
438
439 void CallMethod(jobject o, jclass c, jmethodID m, bool nonstatic, const char* test_case) {
440 printf("RUNNING %s\n", test_case);
441 env_->CallNonvirtualVoidMethod(o, c, m);
442 bool exception_check = env_->ExceptionCheck();
443 if (c == nullptr || !nonstatic) {
444 if (!exception_check) {
445 printf("FAILED %s due to missing exception\n", test_case);
446 env_->FatalError("Expected NullPointerException with null jclass");
447 }
448 env_->ExceptionClear();
449 } else if (exception_check) {
450 printf("FAILED %s due to pending exception\n", test_case);
451 env_->ExceptionDescribe();
452 env_->FatalError(test_case);
453 }
454 printf("PASSED %s\n", test_case);
455 }
456
457 jfieldID GetFieldID(jclass c, const char* field_name) {
458 jfieldID m = env_->GetFieldID(c, field_name, "Z");
459 if (env_->ExceptionCheck()) {
460 env_->ExceptionDescribe();
461 env_->FatalError(__FUNCTION__);
462 }
463 assert(m != nullptr);
464 return m;
465 }
466
467 jboolean GetBooleanField(jobject o, jfieldID f) {
468 jboolean b = env_->GetBooleanField(o, f);
469 if (env_->ExceptionCheck()) {
470 env_->ExceptionDescribe();
471 env_->FatalError(__FUNCTION__);
472 }
473 return b;
474 }
475
476 void TestStaticCallNonvirtualMethod() {
477 if (!check_jni_ri_&& !check_jni_android_) {
478 CallMethod(nullptr, nullptr, super_static_, false, "null object, null class, super static");
479 }
480 if (!check_jni_android_) {
481 CallMethod(nullptr, super_, super_static_, false, "null object, super class, super static");
482 }
483 if (!check_jni_android_) {
484 CallMethod(nullptr, sub_, super_static_, false, "null object, sub class, super static");
485 }
486
487 if (!check_jni_ri_ && !check_jni_android_) {
488 CallMethod(nullptr, nullptr, sub_static_, false, "null object, null class, sub static");
489 }
490 if (!check_jni_android_) {
491 CallMethod(nullptr, sub_, sub_static_, false, "null object, super class, sub static");
492 }
493 if (!check_jni_android_) {
494 CallMethod(nullptr, super_, sub_static_, false, "null object, super class, sub static");
495 }
496 }
497
498 void TestNewObject() {
499 jobject super_super = CallConstructor(super_, super_constructor_);
500 jobject super_sub = CallConstructor(super_, sub_constructor_);
501 jobject sub_super = CallConstructor(sub_, super_constructor_);
502 jobject sub_sub = CallConstructor(sub_, sub_constructor_);
503
504 assert(env_->IsInstanceOf(super_super, super_));
505 assert(!env_->IsInstanceOf(super_super, sub_));
506
507 // Note that even though we called (and ran) the subclass
508 // constructor, we are not the subclass.
509 assert(env_->IsInstanceOf(super_sub, super_));
510 assert(!env_->IsInstanceOf(super_sub, sub_));
511
512 // Note that even though we called the superclass constructor, we
513 // are still the subclass.
514 assert(env_->IsInstanceOf(sub_super, super_));
515 assert(env_->IsInstanceOf(sub_super, sub_));
516
517 assert(env_->IsInstanceOf(sub_sub, super_));
518 assert(env_->IsInstanceOf(sub_sub, sub_));
519 }
520
521 void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) {
522 if (check_jni_android_) {
523 if (super_object && !super_method) {
524 return; // We don't allow a call with sub class method on the super class instance.
525 }
526 if (super_class && !super_method) {
527 return; // We don't allow a call with the sub class method with the super class argument.
528 }
529 }
530 jobject o = ((super_object) ?
531 CallConstructor(super_, super_constructor_) :
532 CallConstructor(sub_, sub_constructor_));
533 jclass c = (super_class) ? super_ : sub_;
534 jmethodID m = (super_method) ? super_nonstatic_ : sub_nonstatic_;
535 CallMethod(o, c, m, true, test_case);
536 jboolean super_field = GetBooleanField(o, super_field_);
537 jboolean sub_field = GetBooleanField(o, sub_field_);
538 assert(super_field == super_method);
539 assert(sub_field != super_method);
540 }
541
542 void TestnonstaticCallNonvirtualMethod() {
543 TestnonstaticCallNonvirtualMethod(true, true, true, "super object, super class, super nonstatic");
544 TestnonstaticCallNonvirtualMethod(true, false, true, "super object, sub class, super nonstatic");
545 TestnonstaticCallNonvirtualMethod(true, false, false, "super object, sub class, sub nonstatic");
546 TestnonstaticCallNonvirtualMethod(true, true, false, "super object, super class, sub nonstatic");
547
548 TestnonstaticCallNonvirtualMethod(false, true, true, "sub object, super class, super nonstatic");
549 TestnonstaticCallNonvirtualMethod(false, false, true, "sub object, sub class, super nonstatic");
550 TestnonstaticCallNonvirtualMethod(false, false, false, "sub object, sub class, sub nonstatic");
551 TestnonstaticCallNonvirtualMethod(false, true, false, "sub object, super class, sub nonstatic");
552 }
553};
554
555extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) {
556 JniCallNonvirtualVoidMethodTest(env).Test();
557}
Jeff Hao848f70a2014-01-15 13:49:50 -0800558
559extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) {
Jeff Hao848f70a2014-01-15 13:49:50 -0800560 jclass c = env->FindClass("java/lang/String");
Jeff Hao39b6c242015-05-19 20:30:23 -0700561 assert(c != nullptr);
562
563 jmethodID mid1 = env->GetMethodID(c, "<init>", "()V");
564 assert(mid1 != nullptr);
Jeff Hao848f70a2014-01-15 13:49:50 -0800565 assert(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700566 jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V");
567 assert(mid2 != nullptr);
568 assert(!env->ExceptionCheck());
569 jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V");
570 assert(mid3 != nullptr);
571 assert(!env->ExceptionCheck());
572 jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
573 assert(mid4 != nullptr);
574 assert(!env->ExceptionCheck());
575
576 const char* test_array = "Test";
577 int byte_array_length = strlen(test_array);
578 jbyteArray byte_array = env->NewByteArray(byte_array_length);
579 env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array));
580
581 // Test NewObject
582 jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array));
583 assert(s != nullptr);
584 assert(env->GetStringLength(s) == byte_array_length);
585 assert(env->GetStringUTFLength(s) == byte_array_length);
Jeff Hao848f70a2014-01-15 13:49:50 -0800586 const char* chars = env->GetStringUTFChars(s, nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700587 assert(strcmp(test_array, chars) == 0);
Jeff Hao848f70a2014-01-15 13:49:50 -0800588 env->ReleaseStringUTFChars(s, chars);
Jeff Hao39b6c242015-05-19 20:30:23 -0700589
590 // Test AllocObject and Call(Nonvirtual)VoidMethod
591 jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c));
592 assert(s1 != nullptr);
593 jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c));
594 assert(s2 != nullptr);
595 jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c));
596 assert(s3 != nullptr);
597 jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c));
598 assert(s4 != nullptr);
599
600 jcharArray char_array = env->NewCharArray(5);
601 jstring string_arg = env->NewStringUTF("helloworld");
602
603 // With Var Args
604 env->CallVoidMethod(s1, mid1);
605 env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array);
606
607 // With JValues
608 jvalue args3[1];
609 args3[0].l = char_array;
610 jvalue args4[1];
611 args4[0].l = string_arg;
612 env->CallVoidMethodA(s3, mid3, args3);
613 env->CallNonvirtualVoidMethodA(s4, c, mid4, args4);
Jeff Hao450c62b2015-05-28 14:32:07 -0700614
615 // Test with global and weak global references
616 jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
617 assert(s5 != nullptr);
618 s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
619 jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
620 assert(s6 != nullptr);
621 s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));
622
623 env->CallVoidMethod(s5, mid1);
624 env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
625 assert(env->GetStringLength(s5) == 0);
626 assert(env->GetStringLength(s6) == byte_array_length);
627 const char* chars6 = env->GetStringUTFChars(s6, nullptr);
628 assert(strcmp(test_array, chars6) == 0);
629 env->ReleaseStringUTFChars(s6, chars6);
Jeff Hao848f70a2014-01-15 13:49:50 -0800630}
Mathieu Chartier72156e22015-07-10 18:26:41 -0700631
632extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) {
633 return reinterpret_cast<jlong>(env->GetMethodID(c, "a", "()V"));
634}