blob: bb18a707f4dc9c9f00b43cd5c644e39c2b194c78 [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
Mathieu Chartier598302a2015-09-23 14:52:39 -070017#include <iostream>
Brian Carlstromce888532013-10-10 00:32:58 -070018#include <pthread.h>
Mathieu Chartier598302a2015-09-23 14:52:39 -070019#include <stdio.h>
Narayan Kamathef809d02013-12-19 17:52:47 +000020#include <vector>
Brian Carlstromce888532013-10-10 00:32:58 -070021
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070022#include "art_method-inl.h"
23#include "base/logging.h"
Brian Carlstromce888532013-10-10 00:32:58 -070024#include "jni.h"
25
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070026namespace art {
Brian Carlstromce888532013-10-10 00:32:58 -070027
Mathieu Chartier2cebb242015-04-21 16:50:40 -070028static JavaVM* jvm = nullptr;
Brian Carlstromce888532013-10-10 00:32:58 -070029
Igor Murashkin9d4b6da2016-07-29 09:51:58 -070030static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c);
31
32static JNINativeMethod sMainMethods[] = {
33 {"intFastNativeMethod", "(III)I", reinterpret_cast<void*>(Java_Main_intFastNativeMethod) }
34};
35
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -070036extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) {
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070037 CHECK(vm != nullptr);
38 CHECK(jvm == nullptr);
Brian Carlstromce888532013-10-10 00:32:58 -070039 jvm = vm;
Mathieu Chartier598302a2015-09-23 14:52:39 -070040 std::cout << "JNI_OnLoad called" << std::endl;
Igor Murashkin9d4b6da2016-07-29 09:51:58 -070041
Brian Carlstromce888532013-10-10 00:32:58 -070042 return JNI_VERSION_1_6;
43}
44
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -070045extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void*) {
46 // std::cout since LOG(INFO) adds extra stuff like pid.
47 std::cout << "JNI_OnUnload called" << std::endl;
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070048 // Clear jvm for CHECK in test 004-JniTest.
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -070049 jvm = nullptr;
50}
51
Andreas Gampe718ac652014-08-11 18:51:53 -070052static void* AttachHelper(void* arg) {
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070053 CHECK(jvm != nullptr);
Brian Carlstromce888532013-10-10 00:32:58 -070054
Andreas Gampe718ac652014-08-11 18:51:53 -070055 JNIEnv* env = nullptr;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070056 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr };
Brian Carlstromce888532013-10-10 00:32:58 -070057 int attach_result = jvm->AttachCurrentThread(&env, &args);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070058 CHECK_EQ(attach_result, 0);
Brian Carlstromce888532013-10-10 00:32:58 -070059
Andreas Gampe718ac652014-08-11 18:51:53 -070060 typedef void (*Fn)(JNIEnv*);
61 Fn fn = reinterpret_cast<Fn>(arg);
62 fn(env);
Brian Carlstromce888532013-10-10 00:32:58 -070063
64 int detach_result = jvm->DetachCurrentThread();
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070065 CHECK_EQ(detach_result, 0);
Andreas Gampe718ac652014-08-11 18:51:53 -070066 return nullptr;
67}
68
69static void PthreadHelper(void (*fn)(JNIEnv*)) {
70 pthread_t pthread;
71 int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
72 reinterpret_cast<void*>(fn));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070073 CHECK_EQ(pthread_create_result, 0);
Andreas Gampe718ac652014-08-11 18:51:53 -070074 int pthread_join_result = pthread_join(pthread, nullptr);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070075 CHECK_EQ(pthread_join_result, 0);
Andreas Gampe718ac652014-08-11 18:51:53 -070076}
77
78static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
79 jclass clazz = env->FindClass("Main");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070080 CHECK(clazz != nullptr);
81 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -070082
83 jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070084 CHECK(array != nullptr);
85 CHECK(!env->ExceptionCheck());
Brian Carlstromce888532013-10-10 00:32:58 -070086}
87
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070088// http://b/10994325
Andreas Gampe718ac652014-08-11 18:51:53 -070089extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) {
90 PthreadHelper(&testFindClassOnAttachedNativeThread);
Brian Carlstromce888532013-10-10 00:32:58 -070091}
Brian Carlstrom67fe2b42013-10-15 18:51:42 -070092
Andreas Gampe718ac652014-08-11 18:51:53 -070093static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070094 jclass clazz = env->FindClass("Main");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070095 CHECK(clazz != nullptr);
96 CHECK(!env->ExceptionCheck());
Jeff Hao62509b62013-12-10 17:44:56 -080097
98 jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -070099 CHECK(field != nullptr);
100 CHECK(!env->ExceptionCheck());
Jeff Hao62509b62013-12-10 17:44:56 -0800101
102 env->SetStaticBooleanField(clazz, field, JNI_TRUE);
Jeff Hao62509b62013-12-10 17:44:56 -0800103}
104
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700105extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -0700106 jclass) {
107 PthreadHelper(&testFindFieldOnAttachedNativeThread);
Jeff Hao62509b62013-12-10 17:44:56 -0800108}
109
Andreas Gampe718ac652014-08-11 18:51:53 -0700110static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700111 jclass clazz = env->FindClass("Main");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700112 CHECK(clazz != nullptr);
113 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100114
115 jclass class_clazz = env->FindClass("java/lang/Class");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700116 CHECK(class_clazz != nullptr);
117 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100118
119 jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
120 "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700121 CHECK(getFieldMetodId != nullptr);
122 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100123
124 jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700125 CHECK(field_name != nullptr);
126 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100127
128 jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700129 CHECK(field != nullptr);
130 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100131
132 jclass field_clazz = env->FindClass("java/lang/reflect/Field");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700133 CHECK(field_clazz != nullptr);
134 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100135
136 jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
137 "(Ljava/lang/Object;)Z");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700138 CHECK(getBooleanMetodId != nullptr);
139 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100140
141 jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700142 CHECK(value == false);
143 CHECK(!env->ExceptionCheck());
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100144}
145
146// http://b/15539150
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700147extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100148 JNIEnv*, jclass) {
Andreas Gampe718ac652014-08-11 18:51:53 -0700149 PthreadHelper(&testReflectFieldGetFromAttachedNativeThread);
Vladimir Marko3bd7a6c2014-06-12 15:22:31 +0100150}
151
Jeff Hao62509b62013-12-10 17:44:56 -0800152
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700153// http://b/11243757
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700154extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
Andreas Gampe718ac652014-08-11 18:51:53 -0700155 jclass) {
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700156 jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700157 CHECK(super_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700158
159 jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700160 CHECK(execute != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700161
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700162 jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700163 CHECK(sub_class != nullptr);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700164
165 env->CallStaticVoidMethod(sub_class, execute);
166}
Jeff Hao201803f2013-11-20 18:11:39 -0800167
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700168extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
169 jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700170 CHECK(abstract_class != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800171 jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700172 CHECK(miranda_method != nullptr);
Jeff Hao201803f2013-11-20 18:11:39 -0800173 return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
174}
Narayan Kamathef809d02013-12-19 17:52:47 +0000175
176// https://code.google.com/p/android/issues/detail?id=63055
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700177extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
Narayan Kamathef809d02013-12-19 17:52:47 +0000178 std::vector<uint8_t> buffer(1);
179 jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700180 CHECK(byte_buffer != nullptr);
181 CHECK(!env->ExceptionCheck());
Narayan Kamathef809d02013-12-19 17:52:47 +0000182
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700183 CHECK_EQ(env->GetDirectBufferAddress(byte_buffer), &buffer[0]);
184 CHECK_EQ(env->GetDirectBufferCapacity(byte_buffer), 0);
Narayan Kamathef809d02013-12-19 17:52:47 +0000185}
Andreas Gamped1104322014-05-01 14:38:56 -0700186
187constexpr size_t kByteReturnSize = 7;
188jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 };
189
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700190extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700191 jbyte b3, jbyte b4, jbyte b5, jbyte b6,
192 jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700193 // We use b1 to drive the output.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700194 CHECK_EQ(b2, 2);
195 CHECK_EQ(b3, -3);
196 CHECK_EQ(b4, 4);
197 CHECK_EQ(b5, -5);
198 CHECK_EQ(b6, 6);
199 CHECK_EQ(b7, -7);
200 CHECK_EQ(b8, 8);
201 CHECK_EQ(b9, -9);
202 CHECK_EQ(b10, 10);
Andreas Gamped1104322014-05-01 14:38:56 -0700203
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700204 CHECK_LE(0, b1);
205 CHECK_LT(b1, static_cast<jbyte>(kByteReturnSize));
Andreas Gamped1104322014-05-01 14:38:56 -0700206
207 return byte_returns[b1];
208}
209
210constexpr size_t kShortReturnSize = 9;
211jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128,
212 static_cast<jshort>(0x8000) };
213// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768.
214
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700215extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jshort s2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700216 jshort s3, jshort s4, jshort s5, jshort s6,
217 jshort s7, jshort s8, jshort s9, jshort s10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700218 // We use s1 to drive the output.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700219 CHECK_EQ(s2, 2);
220 CHECK_EQ(s3, -3);
221 CHECK_EQ(s4, 4);
222 CHECK_EQ(s5, -5);
223 CHECK_EQ(s6, 6);
224 CHECK_EQ(s7, -7);
225 CHECK_EQ(s8, 8);
226 CHECK_EQ(s9, -9);
227 CHECK_EQ(s10, 10);
Andreas Gamped1104322014-05-01 14:38:56 -0700228
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700229 CHECK_LE(0, s1);
230 CHECK_LT(s1, static_cast<jshort>(kShortReturnSize));
Andreas Gamped1104322014-05-01 14:38:56 -0700231
232 return short_returns[s1];
233}
234
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700235extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1,
Andreas Gampe718ac652014-08-11 18:51:53 -0700236 jboolean b2, jboolean b3, jboolean b4,
237 jboolean b5, jboolean b6, jboolean b7,
238 jboolean b8, jboolean b9, jboolean b10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700239 // We use b1 to drive the output.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700240 CHECK_EQ(b2, JNI_TRUE);
241 CHECK_EQ(b3, JNI_FALSE);
242 CHECK_EQ(b4, JNI_TRUE);
243 CHECK_EQ(b5, JNI_FALSE);
244 CHECK_EQ(b6, JNI_TRUE);
245 CHECK_EQ(b7, JNI_FALSE);
246 CHECK_EQ(b8, JNI_TRUE);
247 CHECK_EQ(b9, JNI_FALSE);
248 CHECK_EQ(b10, JNI_TRUE);
Andreas Gamped1104322014-05-01 14:38:56 -0700249
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700250 CHECK(b1 == JNI_TRUE || b1 == JNI_FALSE);
Andreas Gamped1104322014-05-01 14:38:56 -0700251 return b1;
252}
253
254constexpr size_t kCharReturnSize = 8;
255jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 };
256
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700257extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c2,
Andreas Gampe718ac652014-08-11 18:51:53 -0700258 jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
259 jchar c8, jchar c9, jchar c10) {
Andreas Gamped1104322014-05-01 14:38:56 -0700260 // We use c1 to drive the output.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700261 CHECK_EQ(c2, 'a');
262 CHECK_EQ(c3, 'b');
263 CHECK_EQ(c4, 'c');
264 CHECK_EQ(c5, '0');
265 CHECK_EQ(c6, '1');
266 CHECK_EQ(c7, '2');
267 CHECK_EQ(c8, 1234);
268 CHECK_EQ(c9, 2345);
269 CHECK_EQ(c10, 3456);
Andreas Gamped1104322014-05-01 14:38:56 -0700270
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700271 CHECK_LT(c1, static_cast<jchar>(kCharReturnSize));
Andreas Gamped1104322014-05-01 14:38:56 -0700272
273 return char_returns[c1];
274}
Narayan Kamath1268b742014-07-11 19:15:11 +0100275
Mathieu Chartier22c1caa2015-06-02 13:40:12 -0700276extern "C" JNIEXPORT void JNICALL Java_Main_removeLocalObject(JNIEnv* env, jclass, jclass o) {
277 // Delete the arg to see if it crashes.
278 env->DeleteLocalRef(o);
279}
280
Narayan Kamath1268b742014-07-11 19:15:11 +0100281extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* env, jclass,
282 jclass from, jclass to) {
283 return env->IsAssignableFrom(from, to);
284}
Andreas Gampe718ac652014-08-11 18:51:53 -0700285
286static void testShallowGetCallingClassLoader(JNIEnv* env) {
287 // Test direct call.
288 {
289 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700290 CHECK(vmstack_clazz != nullptr);
291 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700292
293 jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
294 "getCallingClassLoader",
295 "()Ljava/lang/ClassLoader;");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700296 CHECK(getCallingClassLoaderMethodId != nullptr);
297 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700298
299 jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
300 getCallingClassLoaderMethodId);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700301 CHECK(class_loader == nullptr);
302 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700303 }
304
305 // Test one-level call. Use System.loadLibrary().
306 {
307 jclass system_clazz = env->FindClass("java/lang/System");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700308 CHECK(system_clazz != nullptr);
309 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700310
311 jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
312 "(Ljava/lang/String;)V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700313 CHECK(loadLibraryMethodId != nullptr);
314 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700315
316 // Create a string object.
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000317 jobject library_string = env->NewStringUTF("non_existing_library");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700318 CHECK(library_string != nullptr);
319 CHECK(!env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700320
321 env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700322 CHECK(env->ExceptionCheck());
Andreas Gampe718ac652014-08-11 18:51:53 -0700323
Nicolas Geoffray005f6972014-12-03 18:10:39 +0000324 // We expect UnsatisfiedLinkError.
325 jthrowable thrown = env->ExceptionOccurred();
326 env->ExceptionClear();
327
328 jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
329 jclass thrown_class = env->GetObjectClass(thrown);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700330 CHECK(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
Andreas Gampe718ac652014-08-11 18:51:53 -0700331 }
332}
333
334// http://b/16867274
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700335extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv*,
Andreas Gampe718ac652014-08-11 18:51:53 -0700336 jclass) {
337 PthreadHelper(&testShallowGetCallingClassLoader);
338}
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700339
340static void testShallowGetStackClass2(JNIEnv* env) {
341 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700342 CHECK(vmstack_clazz != nullptr);
343 CHECK(!env->ExceptionCheck());
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700344
345 // Test direct call.
346 {
347 jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2",
348 "()Ljava/lang/Class;");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700349 CHECK(getStackClass2MethodId != nullptr);
350 CHECK(!env->ExceptionCheck());
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700351
352 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700353 CHECK(caller_class == nullptr);
354 CHECK(!env->ExceptionCheck());
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700355 }
356
357 // Test one-level call. Use VMStack.getStackClass1().
358 {
359 jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1",
360 "()Ljava/lang/Class;");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700361 CHECK(getStackClass1MethodId != nullptr);
362 CHECK(!env->ExceptionCheck());
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700363
364 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700365 CHECK(caller_class == nullptr);
366 CHECK(!env->ExceptionCheck());
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700367 }
368
369 // For better testing we would need to compile against libcore and have a two-deep stack
370 // ourselves.
371}
372
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700373extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetStackClass2(JNIEnv*, jclass) {
Andreas Gampe0d334ce2014-08-13 23:05:38 -0700374 PthreadHelper(&testShallowGetStackClass2);
375}
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700376
377class JniCallNonvirtualVoidMethodTest {
378 public:
379 explicit JniCallNonvirtualVoidMethodTest(JNIEnv* env)
380 : env_(env),
381 check_jni_ri_(true),
382 check_jni_android_(true),
383 super_(GetClass("JniCallNonvirtualTest")),
384 sub_(GetClass("JniCallNonvirtualTestSubclass")),
385 super_constructor_(GetMethodID(super_, true, "<init>")),
386 super_static_(GetMethodID(super_, false, "staticMethod")),
387 super_nonstatic_(GetMethodID(super_, true, "nonstaticMethod")),
388 sub_constructor_(GetMethodID(sub_, true, "<init>")),
389 sub_static_(GetMethodID(sub_, false, "staticMethod")),
390 sub_nonstatic_(GetMethodID(sub_, true, "nonstaticMethod")),
391 super_field_(GetFieldID(super_, "nonstaticMethodSuperCalled")),
392 sub_field_(GetFieldID(super_, "nonstaticMethodSubCalled")) {}
393
394 void Test() {
395 TestStaticCallNonvirtualMethod();
396 TestNewObject();
397 TestnonstaticCallNonvirtualMethod();
398 }
399
400 JNIEnv* const env_;
401
402 bool const check_jni_ri_;
403 bool const check_jni_android_;
404
405 jclass const super_;
406 jclass const sub_;
407
408 jmethodID const super_constructor_;
409 jmethodID const super_static_;
410 jmethodID const super_nonstatic_;
411 jmethodID const sub_constructor_;
412 jmethodID const sub_static_;
413 jmethodID const sub_nonstatic_;
414
415 jfieldID const super_field_;
416 jfieldID const sub_field_;
417
418 private:
419 jclass GetClass(const char* class_name) {
420 jclass c = env_->FindClass(class_name);
421 if (env_->ExceptionCheck()) {
422 env_->ExceptionDescribe();
423 env_->FatalError(__FUNCTION__);
424 }
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700425 CHECK(!env_->ExceptionCheck());
426 CHECK(c != nullptr);
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700427 return c;
428 }
429
430 jmethodID GetMethodID(jclass c, bool nonstatic, const char* method_name) {
431 jmethodID m = ((nonstatic) ?
432 env_->GetMethodID(c, method_name, "()V") :
433 env_->GetStaticMethodID(c, method_name, "()V"));
434 if (env_->ExceptionCheck()) {
435 env_->ExceptionDescribe();
436 env_->FatalError(__FUNCTION__);
437 }
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700438 CHECK(m != nullptr);
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700439 return m;
440 }
441
442 jobject CallConstructor(jclass c, jmethodID m) {
443 jobject o = env_->NewObject(c, m);
444 if (env_->ExceptionCheck()) {
445 env_->ExceptionDescribe();
446 env_->FatalError(__FUNCTION__);
447 }
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700448 CHECK(o != nullptr);
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700449 return o;
450 }
451
452 void CallMethod(jobject o, jclass c, jmethodID m, bool nonstatic, const char* test_case) {
453 printf("RUNNING %s\n", test_case);
454 env_->CallNonvirtualVoidMethod(o, c, m);
455 bool exception_check = env_->ExceptionCheck();
456 if (c == nullptr || !nonstatic) {
457 if (!exception_check) {
458 printf("FAILED %s due to missing exception\n", test_case);
459 env_->FatalError("Expected NullPointerException with null jclass");
460 }
461 env_->ExceptionClear();
462 } else if (exception_check) {
463 printf("FAILED %s due to pending exception\n", test_case);
464 env_->ExceptionDescribe();
465 env_->FatalError(test_case);
466 }
467 printf("PASSED %s\n", test_case);
468 }
469
470 jfieldID GetFieldID(jclass c, const char* field_name) {
471 jfieldID m = env_->GetFieldID(c, field_name, "Z");
472 if (env_->ExceptionCheck()) {
473 env_->ExceptionDescribe();
474 env_->FatalError(__FUNCTION__);
475 }
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700476 CHECK(m != nullptr);
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700477 return m;
478 }
479
480 jboolean GetBooleanField(jobject o, jfieldID f) {
481 jboolean b = env_->GetBooleanField(o, f);
482 if (env_->ExceptionCheck()) {
483 env_->ExceptionDescribe();
484 env_->FatalError(__FUNCTION__);
485 }
486 return b;
487 }
488
489 void TestStaticCallNonvirtualMethod() {
490 if (!check_jni_ri_&& !check_jni_android_) {
491 CallMethod(nullptr, nullptr, super_static_, false, "null object, null class, super static");
492 }
493 if (!check_jni_android_) {
494 CallMethod(nullptr, super_, super_static_, false, "null object, super class, super static");
495 }
496 if (!check_jni_android_) {
497 CallMethod(nullptr, sub_, super_static_, false, "null object, sub class, super static");
498 }
499
500 if (!check_jni_ri_ && !check_jni_android_) {
501 CallMethod(nullptr, nullptr, sub_static_, false, "null object, null class, sub static");
502 }
503 if (!check_jni_android_) {
504 CallMethod(nullptr, sub_, sub_static_, false, "null object, super class, sub static");
505 }
506 if (!check_jni_android_) {
507 CallMethod(nullptr, super_, sub_static_, false, "null object, super class, sub static");
508 }
509 }
510
511 void TestNewObject() {
512 jobject super_super = CallConstructor(super_, super_constructor_);
513 jobject super_sub = CallConstructor(super_, sub_constructor_);
514 jobject sub_super = CallConstructor(sub_, super_constructor_);
515 jobject sub_sub = CallConstructor(sub_, sub_constructor_);
516
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700517 CHECK(env_->IsInstanceOf(super_super, super_));
518 CHECK(!env_->IsInstanceOf(super_super, sub_));
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700519
520 // Note that even though we called (and ran) the subclass
521 // constructor, we are not the subclass.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700522 CHECK(env_->IsInstanceOf(super_sub, super_));
523 CHECK(!env_->IsInstanceOf(super_sub, sub_));
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700524
525 // Note that even though we called the superclass constructor, we
526 // are still the subclass.
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700527 CHECK(env_->IsInstanceOf(sub_super, super_));
528 CHECK(env_->IsInstanceOf(sub_super, sub_));
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700529
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700530 CHECK(env_->IsInstanceOf(sub_sub, super_));
531 CHECK(env_->IsInstanceOf(sub_sub, sub_));
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700532 }
533
534 void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) {
535 if (check_jni_android_) {
536 if (super_object && !super_method) {
537 return; // We don't allow a call with sub class method on the super class instance.
538 }
539 if (super_class && !super_method) {
540 return; // We don't allow a call with the sub class method with the super class argument.
541 }
542 }
543 jobject o = ((super_object) ?
544 CallConstructor(super_, super_constructor_) :
545 CallConstructor(sub_, sub_constructor_));
546 jclass c = (super_class) ? super_ : sub_;
547 jmethodID m = (super_method) ? super_nonstatic_ : sub_nonstatic_;
548 CallMethod(o, c, m, true, test_case);
549 jboolean super_field = GetBooleanField(o, super_field_);
550 jboolean sub_field = GetBooleanField(o, sub_field_);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700551 CHECK_EQ(super_field, super_method);
552 CHECK_NE(sub_field, super_method);
Brian Carlstrom58e5e5d2014-09-07 23:52:02 -0700553 }
554
555 void TestnonstaticCallNonvirtualMethod() {
556 TestnonstaticCallNonvirtualMethod(true, true, true, "super object, super class, super nonstatic");
557 TestnonstaticCallNonvirtualMethod(true, false, true, "super object, sub class, super nonstatic");
558 TestnonstaticCallNonvirtualMethod(true, false, false, "super object, sub class, sub nonstatic");
559 TestnonstaticCallNonvirtualMethod(true, true, false, "super object, super class, sub nonstatic");
560
561 TestnonstaticCallNonvirtualMethod(false, true, true, "sub object, super class, super nonstatic");
562 TestnonstaticCallNonvirtualMethod(false, false, true, "sub object, sub class, super nonstatic");
563 TestnonstaticCallNonvirtualMethod(false, false, false, "sub object, sub class, sub nonstatic");
564 TestnonstaticCallNonvirtualMethod(false, true, false, "sub object, super class, sub nonstatic");
565 }
566};
567
568extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) {
569 JniCallNonvirtualVoidMethodTest(env).Test();
570}
Jeff Hao848f70a2014-01-15 13:49:50 -0800571
572extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) {
Jeff Hao848f70a2014-01-15 13:49:50 -0800573 jclass c = env->FindClass("java/lang/String");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700574 CHECK(c != nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700575
576 jmethodID mid1 = env->GetMethodID(c, "<init>", "()V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700577 CHECK(mid1 != nullptr);
578 CHECK(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700579 jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700580 CHECK(mid2 != nullptr);
581 CHECK(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700582 jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700583 CHECK(mid3 != nullptr);
584 CHECK(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700585 jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700586 CHECK(mid4 != nullptr);
587 CHECK(!env->ExceptionCheck());
Jeff Hao39b6c242015-05-19 20:30:23 -0700588
589 const char* test_array = "Test";
590 int byte_array_length = strlen(test_array);
591 jbyteArray byte_array = env->NewByteArray(byte_array_length);
592 env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array));
593
594 // Test NewObject
595 jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700596 CHECK(s != nullptr);
597 CHECK_EQ(env->GetStringLength(s), byte_array_length);
598 CHECK_EQ(env->GetStringUTFLength(s), byte_array_length);
Jeff Hao848f70a2014-01-15 13:49:50 -0800599 const char* chars = env->GetStringUTFChars(s, nullptr);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700600 CHECK_EQ(strcmp(test_array, chars), 0);
Jeff Hao848f70a2014-01-15 13:49:50 -0800601 env->ReleaseStringUTFChars(s, chars);
Jeff Hao39b6c242015-05-19 20:30:23 -0700602
603 // Test AllocObject and Call(Nonvirtual)VoidMethod
604 jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700605 CHECK(s1 != nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700606 jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700607 CHECK(s2 != nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700608 jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700609 CHECK(s3 != nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700610 jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700611 CHECK(s4 != nullptr);
Jeff Hao39b6c242015-05-19 20:30:23 -0700612
613 jcharArray char_array = env->NewCharArray(5);
614 jstring string_arg = env->NewStringUTF("helloworld");
615
616 // With Var Args
617 env->CallVoidMethod(s1, mid1);
618 env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array);
619
620 // With JValues
621 jvalue args3[1];
622 args3[0].l = char_array;
623 jvalue args4[1];
624 args4[0].l = string_arg;
625 env->CallVoidMethodA(s3, mid3, args3);
626 env->CallNonvirtualVoidMethodA(s4, c, mid4, args4);
Jeff Hao450c62b2015-05-28 14:32:07 -0700627
628 // Test with global and weak global references
629 jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700630 CHECK(s5 != nullptr);
Jeff Hao450c62b2015-05-28 14:32:07 -0700631 s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
632 jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700633 CHECK(s6 != nullptr);
Jeff Hao450c62b2015-05-28 14:32:07 -0700634 s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));
635
636 env->CallVoidMethod(s5, mid1);
637 env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700638 CHECK_EQ(env->GetStringLength(s5), 0);
639 CHECK_EQ(env->GetStringLength(s6), byte_array_length);
Jeff Hao450c62b2015-05-28 14:32:07 -0700640 const char* chars6 = env->GetStringUTFChars(s6, nullptr);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700641 CHECK_EQ(strcmp(test_array, chars6), 0);
Jeff Hao450c62b2015-05-28 14:32:07 -0700642 env->ReleaseStringUTFChars(s6, chars6);
Jeff Hao848f70a2014-01-15 13:49:50 -0800643}
Mathieu Chartier72156e22015-07-10 18:26:41 -0700644
645extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) {
646 return reinterpret_cast<jlong>(env->GetMethodID(c, "a", "()V"));
647}
Hiroshi Yamauchi20a0be02016-02-19 15:44:06 -0800648
649extern "C" JNIEXPORT void JNICALL Java_Main_enterJniCriticalSection(JNIEnv* env, jclass,
650 jint arraySize,
651 jbyteArray array0,
652 jbyteArray array1) {
653 for (int i = 0; i < 50000; ++i) {
654 char* data0 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array0, nullptr));
655 char* data1 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array1, nullptr));
656 bool up = i % 2 == 0;
657 for (int j = 0; j < arraySize; ++j) {
658 if (up) {
659 data1[j] = data0[j] + 1;
660 } else {
661 data0[j] = data1[j] + 1;
662 }
663 }
664 env->ReleasePrimitiveArrayCritical(array1, data1, 0);
665 env->ReleasePrimitiveArrayCritical(array0, data0, 0);
666 }
667}
Alex Light36121492016-02-22 13:43:29 -0800668
669class JniCallDefaultMethodsTest {
670 public:
671 explicit JniCallDefaultMethodsTest(JNIEnv* env)
672 : env_(env), concrete_class_(env_->FindClass("ConcreteClass")) {
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700673 CHECK(!env_->ExceptionCheck());
674 CHECK(concrete_class_ != nullptr);
Alex Light36121492016-02-22 13:43:29 -0800675 }
676
677 void Test() {
678 TestCalls("ConcreteClass", { "JniCallNonOverridenDefaultMethod",
679 "JniCallOverridenDefaultMethod",
680 "JniCallOverridenDefaultMethodWithSuper",
681 "JniCallOverridenAbstractMethod",
682 "JniCallConflictDefaultMethod",
683 "JniCallSoftConflictMethod" });
684 TestCalls("DefaultInterface", { "JniCallNonOverridenDefaultMethod",
685 "JniCallOverridenDefaultMethod",
686 "JniCallOverridenAbstractMethod",
687 "JniCallConflictDefaultMethod",
688 "JniCallSoftConflictMethod" });
689 TestCalls("AbstractInterface", { "JniCallSoftConflictMethod" });
690 TestCalls("ConflictInterface", { "JniCallConflictDefaultMethod" });
691 }
692
693 private:
694 void TestCalls(const char* declaring_class, std::vector<const char*> methods) {
695 jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>", "()V");
696 jobject obj = env_->NewObject(concrete_class_, new_method);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700697 CHECK(!env_->ExceptionCheck());
698 CHECK(obj != nullptr);
Alex Light36121492016-02-22 13:43:29 -0800699 jclass decl_class = env_->FindClass(declaring_class);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700700 CHECK(!env_->ExceptionCheck());
701 CHECK(decl_class != nullptr);
Alex Light36121492016-02-22 13:43:29 -0800702 for (const char* method : methods) {
703 jmethodID method_id = env_->GetMethodID(decl_class, method, "()V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700704 CHECK(!env_->ExceptionCheck());
Alex Light36121492016-02-22 13:43:29 -0800705 printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method);
706 env_->CallVoidMethod(obj, method_id);
707 if (env_->ExceptionCheck()) {
708 jthrowable thrown = env_->ExceptionOccurred();
709 env_->ExceptionClear();
710 jmethodID to_string = env_->GetMethodID(
711 env_->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
712 jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700713 CHECK(!env_->ExceptionCheck());
Alex Light36121492016-02-22 13:43:29 -0800714 const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700715 CHECK(!env_->ExceptionCheck());
716 CHECK(exception_string_utf8 != nullptr);
Alex Light36121492016-02-22 13:43:29 -0800717 printf("EXCEPTION OCCURED: %s\n", exception_string_utf8);
718 env_->ReleaseStringUTFChars(exception_string, exception_string_utf8);
719 }
720 }
721 }
722
723 JNIEnv* env_;
724 jclass concrete_class_;
725};
726
727extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) {
728 JniCallDefaultMethodsTest(env).Test();
729}
Alex Lighte9d2ca22016-02-25 16:13:54 -0800730
731static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) {
732 jclass lambda_class = env->FindClass("LambdaInterface");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700733 CHECK(!env->ExceptionCheck());
734 CHECK(lambda_class != nullptr);
Alex Lighte9d2ca22016-02-25 16:13:54 -0800735 jmethodID method_id = env->GetMethodID(lambda_class, method, "()V");
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700736 CHECK(!env->ExceptionCheck());
Alex Lighte9d2ca22016-02-25 16:13:54 -0800737 env->CallVoidMethod(obj, method_id);
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700738 CHECK(!env->ExceptionCheck());
Alex Lighte9d2ca22016-02-25 16:13:54 -0800739}
740
741extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
742 JNIEnv* e, jclass, jobject l) {
743 InvokeSpecificMethod(e, l, "sayHiTwice");
744}
745
746extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) {
747 InvokeSpecificMethod(e, l, "sayHi");
748}
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700749
Igor Murashkin9d4b6da2016-07-29 09:51:58 -0700750// Register on-demand because many tests share this JNI library and
751// we can't unconditionally register them.
752extern "C" JNIEXPORT jboolean JNICALL Java_Main_registerNativesJniTest(JNIEnv* e, jclass kls) {
753 const size_t numMethods = sizeof(sMainMethods)/sizeof(JNINativeMethod);
754
755 if (e->RegisterNatives(kls, sMainMethods, numMethods) < 0) {
756 std::cerr << "RegisterNatives failed for 'Main'" << std::endl;
757 return JNI_FALSE;
758 }
759
760 return JNI_TRUE;
761}
762
763// Annotated with @FastNative in Java code. Doesn't need to be explicitly registered with "!".
764// NOTE: Has to be registered explicitly to avoid mutator lock check failures.
765static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c) {
766 return a + b + c;
767}
768
Mathieu Chartier48b2b3e2016-05-05 15:31:12 -0700769} // namespace art
770