blob: 2bdf8d1e715faadd1b5d4aba5e02ea2becce6bd8 [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
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -070031extern "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
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -070039extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void*) {
40 // std::cout since LOG(INFO) adds extra stuff like pid.
41 std::cout << "JNI_OnUnload called" << std::endl;
42 // Clear jvm for assert in test 004-JniTest.
43 jvm = nullptr;
44}
45
Andreas Gampe718ac652014-08-11 18:51:53 -070046static void* AttachHelper(void* arg) {
47 assert(jvm != nullptr);
Brian Carlstromce888532013-10-10 00:32:58 -070048
Andreas Gampe718ac652014-08-11 18:51:53 -070049 JNIEnv* env = nullptr;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070050 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr };
Brian Carlstromce888532013-10-10 00:32:58 -070051 int attach_result = jvm->AttachCurrentThread(&env, &args);
52 assert(attach_result == 0);
53
Andreas Gampe718ac652014-08-11 18:51:53 -070054 typedef void (*Fn)(JNIEnv*);
55 Fn fn = reinterpret_cast<Fn>(arg);
56 fn(env);
Brian Carlstromce888532013-10-10 00:32:58 -070057
58 int detach_result = jvm->DetachCurrentThread();
59 assert(detach_result == 0);
Andreas Gampe718ac652014-08-11 18:51:53 -070060 return nullptr;
61}
62
63static void PthreadHelper(void (*fn)(JNIEnv*)) {
64 pthread_t pthread;
65 int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
66 reinterpret_cast<void*>(fn));
67 assert(pthread_create_result == 0);
68 int pthread_join_result = pthread_join(pthread, nullptr);
69 assert(pthread_join_result == 0);
70}
71
72static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
73 jclass clazz = env->FindClass("Main");
74 assert(clazz != nullptr);
75 assert(!env->ExceptionCheck());
76
77 jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
78 assert(array != nullptr);
79 assert(!env->ExceptionCheck());
Brian Carlstromce888532013-10-10 00:32:58 -070080}
81
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070082// http://b/10994325
Andreas Gampe718ac652014-08-11 18:51:53 -070083extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) {
84 PthreadHelper(&testFindClassOnAttachedNativeThread);
Brian Carlstromce888532013-10-10 00:32:58 -070085}
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070086
Andreas Gampe718ac652014-08-11 18:51:53 -070087static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070088 jclass clazz = env->FindClass("Main");
Andreas Gampe718ac652014-08-11 18:51:53 -070089 assert(clazz != nullptr);
Jeff Hao62509b62013-12-10 17:44:56 -080090 assert(!env->ExceptionCheck());
91
92 jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z");
Andreas Gampe718ac652014-08-11 18:51:53 -070093 assert(field != nullptr);
Jeff Hao62509b62013-12-10 17:44:56 -080094 assert(!env->ExceptionCheck());
95
96 env->SetStaticBooleanField(clazz, field, JNI_TRUE);
Jeff Hao62509b62013-12-10 17:44:56 -080097}
98
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070099extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -0700100 jclass) {
101 PthreadHelper(&testFindFieldOnAttachedNativeThread);
Jeff Hao62509b62013-12-10 17:44:56 -0800102}
103
Andreas Gampe718ac652014-08-11 18:51:53 -0700104static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700105 jclass clazz = env->FindClass("Main");
Andreas Gampe718ac652014-08-11 18:51:53 -0700106 assert(clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100107 assert(!env->ExceptionCheck());
108
109 jclass class_clazz = env->FindClass("java/lang/Class");
Andreas Gampe718ac652014-08-11 18:51:53 -0700110 assert(class_clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100111 assert(!env->ExceptionCheck());
112
113 jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
114 "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
Andreas Gampe718ac652014-08-11 18:51:53 -0700115 assert(getFieldMetodId != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100116 assert(!env->ExceptionCheck());
117
118 jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
Andreas Gampe718ac652014-08-11 18:51:53 -0700119 assert(field_name != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100120 assert(!env->ExceptionCheck());
121
122 jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
Andreas Gampe718ac652014-08-11 18:51:53 -0700123 assert(field != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100124 assert(!env->ExceptionCheck());
125
126 jclass field_clazz = env->FindClass("java/lang/reflect/Field");
Andreas Gampe718ac652014-08-11 18:51:53 -0700127 assert(field_clazz != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100128 assert(!env->ExceptionCheck());
129
130 jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
131 "(Ljava/lang/Object;)Z");
Andreas Gampe718ac652014-08-11 18:51:53 -0700132 assert(getBooleanMetodId != nullptr);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100133 assert(!env->ExceptionCheck());
134
135 jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
136 assert(value == false);
137 assert(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100138}
139
140// http://b/15539150
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700141extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100142 JNIEnv*, jclass) {
Andreas Gampe718ac652014-08-11 18:51:53 -0700143 PthreadHelper(&testReflectFieldGetFromAttachedNativeThread);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100144}
145
Jeff Hao62509b62013-12-10 17:44:56 -0800146
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700147// http://b/11243757
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700148extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
Andreas Gampe718ac652014-08-11 18:51:53 -0700149 jclass) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700150 jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
Andreas Gampe718ac652014-08-11 18:51:53 -0700151 assert(super_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700152
153 jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V");
Andreas Gampe718ac652014-08-11 18:51:53 -0700154 assert(execute != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700155
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700156 jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
Andreas Gampe718ac652014-08-11 18:51:53 -0700157 assert(sub_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700158
159 env->CallStaticVoidMethod(sub_class, execute);
160}
Jeff Hao201803f2013-11-20 18:11:39 -0800161
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700162extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
163 jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
Andreas Gampe718ac652014-08-11 18:51:53 -0700164 assert(abstract_class != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800165 jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z");
Andreas Gampe718ac652014-08-11 18:51:53 -0700166 assert(miranda_method != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800167 return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
168}
Narayan Kamathef809d02013-12-19 17:52:47 +0000169
170// https://code.google.com/p/android/issues/detail?id=63055
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700171extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
Narayan Kamathef809d02013-12-19 17:52:47 +0000172 std::vector<uint8_t> buffer(1);
173 jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
Andreas Gampe718ac652014-08-11 18:51:53 -0700174 assert(byte_buffer != nullptr);
Narayan Kamathef809d02013-12-19 17:52:47 +0000175 assert(!env->ExceptionCheck());
176
177 assert(env->GetDirectBufferAddress(byte_buffer) == &buffer[0]);
178 assert(env->GetDirectBufferCapacity(byte_buffer) == 0);
179}
Andreas Gamped1104322014-05-01 14:38:56 -0700180
181constexpr size_t kByteReturnSize = 7;
182jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 };
183
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700184extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700185 jbyte b3, jbyte b4, jbyte b5, jbyte b6,
186 jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700187 // We use b1 to drive the output.
188 assert(b2 == 2);
189 assert(b3 == -3);
190 assert(b4 == 4);
191 assert(b5 == -5);
192 assert(b6 == 6);
193 assert(b7 == -7);
194 assert(b8 == 8);
195 assert(b9 == -9);
196 assert(b10 == 10);
197
198 assert(0 <= b1);
199 assert(b1 < static_cast<jbyte>(kByteReturnSize));
200
201 return byte_returns[b1];
202}
203
204constexpr size_t kShortReturnSize = 9;
205jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128,
206 static_cast<jshort>(0x8000) };
207// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768.
208
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700209extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jshort s2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700210 jshort s3, jshort s4, jshort s5, jshort s6,
211 jshort s7, jshort s8, jshort s9, jshort s10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700212 // We use s1 to drive the output.
213 assert(s2 == 2);
214 assert(s3 == -3);
215 assert(s4 == 4);
216 assert(s5 == -5);
217 assert(s6 == 6);
218 assert(s7 == -7);
219 assert(s8 == 8);
220 assert(s9 == -9);
221 assert(s10 == 10);
222
223 assert(0 <= s1);
224 assert(s1 < static_cast<jshort>(kShortReturnSize));
225
226 return short_returns[s1];
227}
228
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700229extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1,
Andreas Gampe718ac652014-08-11 18:51:53 -0700230 jboolean b2, jboolean b3, jboolean b4,
231 jboolean b5, jboolean b6, jboolean b7,
232 jboolean b8, jboolean b9, jboolean b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700233 // We use b1 to drive the output.
234 assert(b2 == JNI_TRUE);
235 assert(b3 == JNI_FALSE);
236 assert(b4 == JNI_TRUE);
237 assert(b5 == JNI_FALSE);
238 assert(b6 == JNI_TRUE);
239 assert(b7 == JNI_FALSE);
240 assert(b8 == JNI_TRUE);
241 assert(b9 == JNI_FALSE);
242 assert(b10 == JNI_TRUE);
243
244 assert(b1 == JNI_TRUE || b1 == JNI_FALSE);
245 return b1;
246}
247
248constexpr size_t kCharReturnSize = 8;
249jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 };
250
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700251extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700252 jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
253 jchar c8, jchar c9, jchar c10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700254 // We use c1 to drive the output.
255 assert(c2 == 'a');
256 assert(c3 == 'b');
257 assert(c4 == 'c');
258 assert(c5 == '0');
259 assert(c6 == '1');
260 assert(c7 == '2');
261 assert(c8 == 1234);
262 assert(c9 == 2345);
263 assert(c10 == 3456);
264
265 assert(c1 < static_cast<jchar>(kCharReturnSize));
266
267 return char_returns[c1];
268}
Narayan Kamath1268b742014-07-11 19:15:11 +0100269
Mathieu Chartier22c1caa2015-06-02 13:40:12 -0700270extern "C" JNIEXPORT void JNICALL Java_Main_removeLocalObject(JNIEnv* env, jclass, jclass o) {
271 // Delete the arg to see if it crashes.
272 env->DeleteLocalRef(o);
273}
274
Narayan Kamath1268b742014-07-11 19:15:11 +0100275extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* env, jclass,
276 jclass from, jclass to) {
277 return env->IsAssignableFrom(from, to);
278}
Andreas Gampe718ac652014-08-11 18:51:53 -0700279
280static void testShallowGetCallingClassLoader(JNIEnv* env) {
281 // Test direct call.
282 {
283 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
284 assert(vmstack_clazz != nullptr);
285 assert(!env->ExceptionCheck());
286
287 jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
288 "getCallingClassLoader",
289 "()Ljava/lang/ClassLoader;");
290 assert(getCallingClassLoaderMethodId != nullptr);
291 assert(!env->ExceptionCheck());
292
293 jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
294 getCallingClassLoaderMethodId);
295 assert(class_loader == nullptr);
296 assert(!env->ExceptionCheck());
297 }
298
299 // Test one-level call. Use System.loadLibrary().
300 {
301 jclass system_clazz = env->FindClass("java/lang/System");
302 assert(system_clazz != nullptr);
303 assert(!env->ExceptionCheck());
304
305 jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
306 "(Ljava/lang/String;)V");
307 assert(loadLibraryMethodId != nullptr);
308 assert(!env->ExceptionCheck());
309
310 // Create a string object.
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000311 jobject library_string = env->NewStringUTF("non_existing_library");
Andreas Gampe718ac652014-08-11 18:51:53 -0700312 assert(library_string != nullptr);
313 assert(!env->ExceptionCheck());
314
315 env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000316 assert(env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700317
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000318 // We expect UnsatisfiedLinkError.
319 jthrowable thrown = env->ExceptionOccurred();
320 env->ExceptionClear();
321
322 jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
323 jclass thrown_class = env->GetObjectClass(thrown);
324 assert(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
Andreas Gampe718ac652014-08-11 18:51:53 -0700325 }
326}
327
328// http://b/16867274
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700329extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -0700330 jclass) {
331 PthreadHelper(&testShallowGetCallingClassLoader);
332}
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700333
334static void testShallowGetStackClass2(JNIEnv* env) {
335 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
336 assert(vmstack_clazz != nullptr);
337 assert(!env->ExceptionCheck());
338
339 // Test direct call.
340 {
341 jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2",
342 "()Ljava/lang/Class;");
343 assert(getStackClass2MethodId != nullptr);
344 assert(!env->ExceptionCheck());
345
346 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId);
347 assert(caller_class == nullptr);
348 assert(!env->ExceptionCheck());
349 }
350
351 // Test one-level call. Use VMStack.getStackClass1().
352 {
353 jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1",
354 "()Ljava/lang/Class;");
355 assert(getStackClass1MethodId != nullptr);
356 assert(!env->ExceptionCheck());
357
358 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId);
359 assert(caller_class == nullptr);
360 assert(!env->ExceptionCheck());
361 }
362
363 // For better testing we would need to compile against libcore and have a two-deep stack
364 // ourselves.
365}
366
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700367extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetStackClass2(JNIEnv*, jclass) {
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700368 PthreadHelper(&testShallowGetStackClass2);
369}
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700370
371class JniCallNonvirtualVoidMethodTest {
372 public:
373 explicit JniCallNonvirtualVoidMethodTest(JNIEnv* env)
374 : env_(env),
375 check_jni_ri_(true),
376 check_jni_android_(true),
377 super_(GetClass("JniCallNonvirtualTest")),
378 sub_(GetClass("JniCallNonvirtualTestSubclass")),
379 super_constructor_(GetMethodID(super_, true, "<init>")),
380 super_static_(GetMethodID(super_, false, "staticMethod")),
381 super_nonstatic_(GetMethodID(super_, true, "nonstaticMethod")),
382 sub_constructor_(GetMethodID(sub_, true, "<init>")),
383 sub_static_(GetMethodID(sub_, false, "staticMethod")),
384 sub_nonstatic_(GetMethodID(sub_, true, "nonstaticMethod")),
385 super_field_(GetFieldID(super_, "nonstaticMethodSuperCalled")),
386 sub_field_(GetFieldID(super_, "nonstaticMethodSubCalled")) {}
387
388 void Test() {
389 TestStaticCallNonvirtualMethod();
390 TestNewObject();
391 TestnonstaticCallNonvirtualMethod();
392 }
393
394 JNIEnv* const env_;
395
396 bool const check_jni_ri_;
397 bool const check_jni_android_;
398
399 jclass const super_;
400 jclass const sub_;
401
402 jmethodID const super_constructor_;
403 jmethodID const super_static_;
404 jmethodID const super_nonstatic_;
405 jmethodID const sub_constructor_;
406 jmethodID const sub_static_;
407 jmethodID const sub_nonstatic_;
408
409 jfieldID const super_field_;
410 jfieldID const sub_field_;
411
412 private:
413 jclass GetClass(const char* class_name) {
414 jclass c = env_->FindClass(class_name);
415 if (env_->ExceptionCheck()) {
416 env_->ExceptionDescribe();
417 env_->FatalError(__FUNCTION__);
418 }
419 assert(!env_->ExceptionCheck());
420 assert(c != nullptr);
421 return c;
422 }
423
424 jmethodID GetMethodID(jclass c, bool nonstatic, const char* method_name) {
425 jmethodID m = ((nonstatic) ?
426 env_->GetMethodID(c, method_name, "()V") :
427 env_->GetStaticMethodID(c, method_name, "()V"));
428 if (env_->ExceptionCheck()) {
429 env_->ExceptionDescribe();
430 env_->FatalError(__FUNCTION__);
431 }
432 assert(m != nullptr);
433 return m;
434 }
435
436 jobject CallConstructor(jclass c, jmethodID m) {
437 jobject o = env_->NewObject(c, m);
438 if (env_->ExceptionCheck()) {
439 env_->ExceptionDescribe();
440 env_->FatalError(__FUNCTION__);
441 }
442 assert(o != nullptr);
443 return o;
444 }
445
446 void CallMethod(jobject o, jclass c, jmethodID m, bool nonstatic, const char* test_case) {
447 printf("RUNNING %s\n", test_case);
448 env_->CallNonvirtualVoidMethod(o, c, m);
449 bool exception_check = env_->ExceptionCheck();
450 if (c == nullptr || !nonstatic) {
451 if (!exception_check) {
452 printf("FAILED %s due to missing exception\n", test_case);
453 env_->FatalError("Expected NullPointerException with null jclass");
454 }
455 env_->ExceptionClear();
456 } else if (exception_check) {
457 printf("FAILED %s due to pending exception\n", test_case);
458 env_->ExceptionDescribe();
459 env_->FatalError(test_case);
460 }
461 printf("PASSED %s\n", test_case);
462 }
463
464 jfieldID GetFieldID(jclass c, const char* field_name) {
465 jfieldID m = env_->GetFieldID(c, field_name, "Z");
466 if (env_->ExceptionCheck()) {
467 env_->ExceptionDescribe();
468 env_->FatalError(__FUNCTION__);
469 }
470 assert(m != nullptr);
471 return m;
472 }
473
474 jboolean GetBooleanField(jobject o, jfieldID f) {
475 jboolean b = env_->GetBooleanField(o, f);
476 if (env_->ExceptionCheck()) {
477 env_->ExceptionDescribe();
478 env_->FatalError(__FUNCTION__);
479 }
480 return b;
481 }
482
483 void TestStaticCallNonvirtualMethod() {
484 if (!check_jni_ri_&& !check_jni_android_) {
485 CallMethod(nullptr, nullptr, super_static_, false, "null object, null class, super static");
486 }
487 if (!check_jni_android_) {
488 CallMethod(nullptr, super_, super_static_, false, "null object, super class, super static");
489 }
490 if (!check_jni_android_) {
491 CallMethod(nullptr, sub_, super_static_, false, "null object, sub class, super static");
492 }
493
494 if (!check_jni_ri_ && !check_jni_android_) {
495 CallMethod(nullptr, nullptr, sub_static_, false, "null object, null class, sub static");
496 }
497 if (!check_jni_android_) {
498 CallMethod(nullptr, sub_, sub_static_, false, "null object, super class, sub static");
499 }
500 if (!check_jni_android_) {
501 CallMethod(nullptr, super_, sub_static_, false, "null object, super class, sub static");
502 }
503 }
504
505 void TestNewObject() {
506 jobject super_super = CallConstructor(super_, super_constructor_);
507 jobject super_sub = CallConstructor(super_, sub_constructor_);
508 jobject sub_super = CallConstructor(sub_, super_constructor_);
509 jobject sub_sub = CallConstructor(sub_, sub_constructor_);
510
511 assert(env_->IsInstanceOf(super_super, super_));
512 assert(!env_->IsInstanceOf(super_super, sub_));
513
514 // Note that even though we called (and ran) the subclass
515 // constructor, we are not the subclass.
516 assert(env_->IsInstanceOf(super_sub, super_));
517 assert(!env_->IsInstanceOf(super_sub, sub_));
518
519 // Note that even though we called the superclass constructor, we
520 // are still the subclass.
521 assert(env_->IsInstanceOf(sub_super, super_));
522 assert(env_->IsInstanceOf(sub_super, sub_));
523
524 assert(env_->IsInstanceOf(sub_sub, super_));
525 assert(env_->IsInstanceOf(sub_sub, sub_));
526 }
527
528 void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) {
529 if (check_jni_android_) {
530 if (super_object && !super_method) {
531 return; // We don't allow a call with sub class method on the super class instance.
532 }
533 if (super_class && !super_method) {
534 return; // We don't allow a call with the sub class method with the super class argument.
535 }
536 }
537 jobject o = ((super_object) ?
538 CallConstructor(super_, super_constructor_) :
539 CallConstructor(sub_, sub_constructor_));
540 jclass c = (super_class) ? super_ : sub_;
541 jmethodID m = (super_method) ? super_nonstatic_ : sub_nonstatic_;
542 CallMethod(o, c, m, true, test_case);
543 jboolean super_field = GetBooleanField(o, super_field_);
544 jboolean sub_field = GetBooleanField(o, sub_field_);
545 assert(super_field == super_method);
546 assert(sub_field != super_method);
547 }
548
549 void TestnonstaticCallNonvirtualMethod() {
550 TestnonstaticCallNonvirtualMethod(true, true, true, "super object, super class, super nonstatic");
551 TestnonstaticCallNonvirtualMethod(true, false, true, "super object, sub class, super nonstatic");
552 TestnonstaticCallNonvirtualMethod(true, false, false, "super object, sub class, sub nonstatic");
553 TestnonstaticCallNonvirtualMethod(true, true, false, "super object, super class, sub nonstatic");
554
555 TestnonstaticCallNonvirtualMethod(false, true, true, "sub object, super class, super nonstatic");
556 TestnonstaticCallNonvirtualMethod(false, false, true, "sub object, sub class, super nonstatic");
557 TestnonstaticCallNonvirtualMethod(false, false, false, "sub object, sub class, sub nonstatic");
558 TestnonstaticCallNonvirtualMethod(false, true, false, "sub object, super class, sub nonstatic");
559 }
560};
561
562extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) {
563 JniCallNonvirtualVoidMethodTest(env).Test();
564}
Jeff Hao848f70a2014-01-15 13:49:50 -0800565
566extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) {
Jeff Hao848f70a2014-01-15 13:49:50 -0800567 jclass c = env->FindClass("java/lang/String");
Jeff Hao39b6c242015-05-19 20:30:23 -0700568 assert(c != nullptr);
569
570 jmethodID mid1 = env->GetMethodID(c, "<init>", "()V");
571 assert(mid1 != nullptr);
Jeff Hao848f70a2014-01-15 13:49:50 -0800572 assert(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700573 jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V");
574 assert(mid2 != nullptr);
575 assert(!env->ExceptionCheck());
576 jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V");
577 assert(mid3 != nullptr);
578 assert(!env->ExceptionCheck());
579 jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
580 assert(mid4 != nullptr);
581 assert(!env->ExceptionCheck());
582
583 const char* test_array = "Test";
584 int byte_array_length = strlen(test_array);
585 jbyteArray byte_array = env->NewByteArray(byte_array_length);
586 env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array));
587
588 // Test NewObject
589 jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array));
590 assert(s != nullptr);
591 assert(env->GetStringLength(s) == byte_array_length);
592 assert(env->GetStringUTFLength(s) == byte_array_length);
Jeff Hao848f70a2014-01-15 13:49:50 -0800593 const char* chars = env->GetStringUTFChars(s, nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700594 assert(strcmp(test_array, chars) == 0);
Jeff Hao848f70a2014-01-15 13:49:50 -0800595 env->ReleaseStringUTFChars(s, chars);
Jeff Hao39b6c242015-05-19 20:30:23 -0700596
597 // Test AllocObject and Call(Nonvirtual)VoidMethod
598 jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c));
599 assert(s1 != nullptr);
600 jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c));
601 assert(s2 != nullptr);
602 jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c));
603 assert(s3 != nullptr);
604 jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c));
605 assert(s4 != nullptr);
606
607 jcharArray char_array = env->NewCharArray(5);
608 jstring string_arg = env->NewStringUTF("helloworld");
609
610 // With Var Args
611 env->CallVoidMethod(s1, mid1);
612 env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array);
613
614 // With JValues
615 jvalue args3[1];
616 args3[0].l = char_array;
617 jvalue args4[1];
618 args4[0].l = string_arg;
619 env->CallVoidMethodA(s3, mid3, args3);
620 env->CallNonvirtualVoidMethodA(s4, c, mid4, args4);
Jeff Hao450c62b2015-05-28 14:32:07 -0700621
622 // Test with global and weak global references
623 jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
624 assert(s5 != nullptr);
625 s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
626 jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
627 assert(s6 != nullptr);
628 s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));
629
630 env->CallVoidMethod(s5, mid1);
631 env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
632 assert(env->GetStringLength(s5) == 0);
633 assert(env->GetStringLength(s6) == byte_array_length);
634 const char* chars6 = env->GetStringUTFChars(s6, nullptr);
635 assert(strcmp(test_array, chars6) == 0);
636 env->ReleaseStringUTFChars(s6, chars6);
Jeff Hao848f70a2014-01-15 13:49:50 -0800637}
Mathieu Chartier72156e22015-07-10 18:26:41 -0700638
639extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) {
640 return reinterpret_cast<jlong>(env->GetMethodID(c, "a", "()V"));
641}
Hiroshi Yamauchi20a0be02016-02-19 15:44:06 -0800642
643extern "C" JNIEXPORT void JNICALL Java_Main_enterJniCriticalSection(JNIEnv* env, jclass,
644 jint arraySize,
645 jbyteArray array0,
646 jbyteArray array1) {
647 for (int i = 0; i < 50000; ++i) {
648 char* data0 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array0, nullptr));
649 char* data1 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array1, nullptr));
650 bool up = i % 2 == 0;
651 for (int j = 0; j < arraySize; ++j) {
652 if (up) {
653 data1[j] = data0[j] + 1;
654 } else {
655 data0[j] = data1[j] + 1;
656 }
657 }
658 env->ReleasePrimitiveArrayCritical(array1, data1, 0);
659 env->ReleasePrimitiveArrayCritical(array0, data0, 0);
660 }
661}
Alex Light36121492016-02-22 13:43:29 -0800662
663class JniCallDefaultMethodsTest {
664 public:
665 explicit JniCallDefaultMethodsTest(JNIEnv* env)
666 : env_(env), concrete_class_(env_->FindClass("ConcreteClass")) {
667 assert(!env_->ExceptionCheck());
668 assert(concrete_class_ != nullptr);
669 }
670
671 void Test() {
672 TestCalls("ConcreteClass", { "JniCallNonOverridenDefaultMethod",
673 "JniCallOverridenDefaultMethod",
674 "JniCallOverridenDefaultMethodWithSuper",
675 "JniCallOverridenAbstractMethod",
676 "JniCallConflictDefaultMethod",
677 "JniCallSoftConflictMethod" });
678 TestCalls("DefaultInterface", { "JniCallNonOverridenDefaultMethod",
679 "JniCallOverridenDefaultMethod",
680 "JniCallOverridenAbstractMethod",
681 "JniCallConflictDefaultMethod",
682 "JniCallSoftConflictMethod" });
683 TestCalls("AbstractInterface", { "JniCallSoftConflictMethod" });
684 TestCalls("ConflictInterface", { "JniCallConflictDefaultMethod" });
685 }
686
687 private:
688 void TestCalls(const char* declaring_class, std::vector<const char*> methods) {
689 jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>", "()V");
690 jobject obj = env_->NewObject(concrete_class_, new_method);
691 assert(!env_->ExceptionCheck());
692 assert(obj != nullptr);
693 jclass decl_class = env_->FindClass(declaring_class);
694 assert(!env_->ExceptionCheck());
695 assert(decl_class != nullptr);
696 for (const char* method : methods) {
697 jmethodID method_id = env_->GetMethodID(decl_class, method, "()V");
698 assert(!env_->ExceptionCheck());
699 printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method);
700 env_->CallVoidMethod(obj, method_id);
701 if (env_->ExceptionCheck()) {
702 jthrowable thrown = env_->ExceptionOccurred();
703 env_->ExceptionClear();
704 jmethodID to_string = env_->GetMethodID(
705 env_->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
706 jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string);
707 assert(!env_->ExceptionCheck());
708 const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr);
709 assert(!env_->ExceptionCheck());
710 assert(exception_string_utf8 != nullptr);
711 printf("EXCEPTION OCCURED: %s\n", exception_string_utf8);
712 env_->ReleaseStringUTFChars(exception_string, exception_string_utf8);
713 }
714 }
715 }
716
717 JNIEnv* env_;
718 jclass concrete_class_;
719};
720
721extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) {
722 JniCallDefaultMethodsTest(env).Test();
723}
Alex Lighte9d2ca22016-02-25 16:13:54 -0800724
725static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) {
726 jclass lambda_class = env->FindClass("LambdaInterface");
727 assert(!env->ExceptionCheck());
728 assert(lambda_class != nullptr);
729 jmethodID method_id = env->GetMethodID(lambda_class, method, "()V");
730 assert(!env->ExceptionCheck());
731 env->CallVoidMethod(obj, method_id);
732 assert(!env->ExceptionCheck());
733}
734
735extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
736 JNIEnv* e, jclass, jobject l) {
737 InvokeSpecificMethod(e, l, "sayHiTwice");
738}
739
740extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) {
741 InvokeSpecificMethod(e, l, "sayHi");
742}