blob: 5d74181cef44ec19d898517c17f0913cebe81f5b [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Elliott Hughes0c9cd562011-08-12 10:59:29 -070016
Carl Shapiro9b9ba282011-08-14 15:30:39 -070017#include "jni_internal.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070018
Andreas Gampe46ee31b2016-12-14 10:11:49 -080019#include "android-base/stringprintf.h"
20
Mathieu Chartiere401d142015-04-22 13:56:20 -070021#include "art_method-inl.h"
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080022#include "common_compiler_test.h"
Andreas Gampeda9b7632015-12-09 15:14:04 -080023#include "indirect_reference_table.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070024#include "java_vm_ext.h"
Andreas Gampeda9b7632015-12-09 15:14:04 -080025#include "jni_env_ext.h"
Fred Shih56890e22014-06-02 11:11:52 -070026#include "mirror/string-inl.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070027#include "nativehelper/scoped_local_ref.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070028#include "scoped_thread_state_change-inl.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070029
30namespace art {
31
Andreas Gampe46ee31b2016-12-14 10:11:49 -080032using android::base::StringPrintf;
33
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080034// TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used.
35class JniInternalTest : public CommonCompilerTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070036 protected:
37 virtual void SetUp() {
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080038 CommonCompilerTest::SetUp();
Elliott Hughes5174fe62011-08-23 15:12:35 -070039
Elliott Hughesa2501992011-08-26 19:39:54 -070040 vm_ = Runtime::Current()->GetJavaVM();
41
Elliott Hughes5174fe62011-08-23 15:12:35 -070042 // Turn on -verbose:jni for the JNI tests.
Ian Rogers79713632013-08-21 19:06:15 -070043 // gLogVerbosity.jni = true;
Elliott Hughes5174fe62011-08-23 15:12:35 -070044
Ian Rogers2d10b202014-05-12 19:15:18 -070045 vm_->AttachCurrentThread(&env_, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -070046
Brian Carlstromea46f952013-07-30 01:26:50 -070047 ScopedLocalRef<jclass> aioobe(env_,
48 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070049 CHECK(aioobe.get() != nullptr);
Elliott Hughes726079d2011-10-07 18:43:44 -070050 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
Elliott Hughesb465ab02011-08-24 11:21:21 -070051
Elliott Hughesb264f082012-04-06 17:10:10 -070052 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070053 CHECK(ase.get() != nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -070054 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
55
Brian Carlstromea46f952013-07-30 01:26:50 -070056 ScopedLocalRef<jclass> sioobe(env_,
57 env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070058 CHECK(sioobe.get() != nullptr);
Elliott Hughes726079d2011-10-07 18:43:44 -070059 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
60 }
61
Ian Rogers2d10b202014-05-12 19:15:18 -070062 void ExpectException(jclass exception_class) {
Ian Rogers68d8b422014-07-17 11:09:10 -070063 ScopedObjectAccess soa(env_);
64 EXPECT_TRUE(env_->ExceptionCheck())
David Sehr709b0702016-10-13 09:12:37 -070065 << mirror::Class::PrettyDescriptor(soa.Decode<mirror::Class>(exception_class));
Ian Rogers2d10b202014-05-12 19:15:18 -070066 jthrowable exception = env_->ExceptionOccurred();
67 EXPECT_NE(nullptr, exception);
68 env_->ExceptionClear();
69 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
70 }
71
Brian Carlstrom4d571432012-05-16 00:21:41 -070072 void CleanUpJniEnv() {
Ian Rogers2d10b202014-05-12 19:15:18 -070073 if (aioobe_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070074 env_->DeleteGlobalRef(aioobe_);
Ian Rogers2d10b202014-05-12 19:15:18 -070075 aioobe_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070076 }
Ian Rogers2d10b202014-05-12 19:15:18 -070077 if (ase_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070078 env_->DeleteGlobalRef(ase_);
Ian Rogers2d10b202014-05-12 19:15:18 -070079 ase_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070080 }
Ian Rogers2d10b202014-05-12 19:15:18 -070081 if (sioobe_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070082 env_->DeleteGlobalRef(sioobe_);
Ian Rogers2d10b202014-05-12 19:15:18 -070083 sioobe_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070084 }
85 }
86
Ian Rogers53b8b092014-03-13 23:45:53 -070087 virtual void TearDown() OVERRIDE {
Brian Carlstrom4d571432012-05-16 00:21:41 -070088 CleanUpJniEnv();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080089 CommonCompilerTest::TearDown();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070090 }
Elliott Hughesb465ab02011-08-24 11:21:21 -070091
Ian Rogers1d99e452014-01-02 17:36:41 -080092 jclass GetPrimitiveClass(char descriptor) {
93 ScopedObjectAccess soa(env_);
94 mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
95 CHECK(c != nullptr);
96 return soa.AddLocalReference<jclass>(c);
97 }
98
Ian Rogers68d8b422014-07-17 11:09:10 -070099 void ExpectClassFound(const char* name) {
100 EXPECT_NE(env_->FindClass(name), nullptr) << name;
101 EXPECT_FALSE(env_->ExceptionCheck()) << name;
102 }
103
104 void ExpectClassNotFound(const char* name, bool check_jni, const char* check_jni_msg,
105 CheckJniAbortCatcher* abort_catcher) {
106 EXPECT_EQ(env_->FindClass(name), nullptr) << name;
107 if (!check_jni || check_jni_msg == nullptr) {
108 EXPECT_TRUE(env_->ExceptionCheck()) << name;
109 env_->ExceptionClear();
110 } else {
111 abort_catcher->Check(check_jni_msg);
112 }
113 }
114
115 void FindClassTest(bool check_jni) {
116 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
117 CheckJniAbortCatcher check_jni_abort_catcher;
118
119 // Null argument is always an abort.
120 env_->FindClass(nullptr);
121 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
122 : "name == null");
123
124 // Reference types...
125 ExpectClassFound("java/lang/String");
126 // ...for arrays too, where you must include "L;".
127 ExpectClassFound("[Ljava/lang/String;");
128 // Primitive arrays are okay too, if the primitive type is valid.
129 ExpectClassFound("[C");
130
131 // But primitive types aren't allowed...
132 ExpectClassNotFound("C", check_jni, nullptr, &check_jni_abort_catcher);
133 ExpectClassNotFound("V", check_jni, nullptr, &check_jni_abort_catcher);
134 ExpectClassNotFound("K", check_jni, nullptr, &check_jni_abort_catcher);
135
136 if (check_jni) {
137 // Check JNI will reject invalid class names as aborts but without pending exceptions.
138 EXPECT_EQ(env_->FindClass("java.lang.String"), nullptr);
139 EXPECT_FALSE(env_->ExceptionCheck());
140 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
141
142 EXPECT_EQ(env_->FindClass("[Ljava.lang.String;"), nullptr);
143 EXPECT_FALSE(env_->ExceptionCheck());
144 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
145 } else {
146 // Without check JNI we're tolerant and replace '.' with '/'.
147 ExpectClassFound("java.lang.String");
148 ExpectClassFound("[Ljava.lang.String;");
149 }
150
151 ExpectClassNotFound("Ljava.lang.String;", check_jni, "illegal class name 'Ljava.lang.String;'",
152 &check_jni_abort_catcher);
153 ExpectClassNotFound("[java.lang.String", check_jni, "illegal class name '[java.lang.String'",
154 &check_jni_abort_catcher);
155
156 // You can't include the "L;" in a JNI class descriptor.
157 ExpectClassNotFound("Ljava/lang/String;", check_jni, "illegal class name 'Ljava/lang/String;'",
158 &check_jni_abort_catcher);
159
160 // But you must include it for an array of any reference type.
161 ExpectClassNotFound("[java/lang/String", check_jni, "illegal class name '[java/lang/String'",
162 &check_jni_abort_catcher);
163
164 ExpectClassNotFound("[K", check_jni, "illegal class name '[K'", &check_jni_abort_catcher);
165
166 // Void arrays aren't allowed.
167 ExpectClassNotFound("[V", check_jni, "illegal class name '[V'", &check_jni_abort_catcher);
168
169 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
170 }
171
172 void GetFieldIdBadArgumentTest(bool check_jni) {
173 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
174 CheckJniAbortCatcher check_jni_abort_catcher;
175
176 jclass c = env_->FindClass("java/lang/String");
177 ASSERT_NE(c, nullptr);
178
179 jfieldID fid = env_->GetFieldID(nullptr, "count", "I");
180 EXPECT_EQ(nullptr, fid);
181 check_jni_abort_catcher.Check(check_jni ? "GetFieldID received NULL jclass"
182 : "java_class == null");
183 fid = env_->GetFieldID(c, nullptr, "I");
184 EXPECT_EQ(nullptr, fid);
185 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
186 : "name == null");
187 fid = env_->GetFieldID(c, "count", nullptr);
188 EXPECT_EQ(nullptr, fid);
189 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
190 : "sig == null");
191
192 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
193 }
194
195 void GetStaticFieldIdBadArgumentTest(bool check_jni) {
196 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
197 CheckJniAbortCatcher check_jni_abort_catcher;
198
199 jclass c = env_->FindClass("java/lang/String");
200 ASSERT_NE(c, nullptr);
201
202 jfieldID fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
203 EXPECT_EQ(nullptr, fid);
204 check_jni_abort_catcher.Check(check_jni ? "GetStaticFieldID received NULL jclass"
205 : "java_class == null");
206 fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
207 EXPECT_EQ(nullptr, fid);
208 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
209 : "name == null");
210 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
211 EXPECT_EQ(nullptr, fid);
212 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
213 : "sig == null");
214
215 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
216 }
217
218 void GetMethodIdBadArgumentTest(bool check_jni) {
219 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
220 CheckJniAbortCatcher check_jni_abort_catcher;
221
222 jmethodID method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
223 EXPECT_EQ(nullptr, method);
224 check_jni_abort_catcher.Check(check_jni ? "GetMethodID received NULL jclass"
225 : "java_class == null");
226 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
227 ASSERT_TRUE(jlnsme != nullptr);
228 method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
229 EXPECT_EQ(nullptr, method);
230 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
231 : "name == null");
232 method = env_->GetMethodID(jlnsme, "<init>", nullptr);
233 EXPECT_EQ(nullptr, method);
234 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
235 : "sig == null");
236
237 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
238 }
239
240 void GetStaticMethodIdBadArgumentTest(bool check_jni) {
241 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
242 CheckJniAbortCatcher check_jni_abort_catcher;
243
244 jmethodID method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
245 EXPECT_EQ(nullptr, method);
246 check_jni_abort_catcher.Check(check_jni ? "GetStaticMethodID received NULL jclass"
247 : "java_class == null");
248 jclass jlstring = env_->FindClass("java/lang/String");
249 method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
250 EXPECT_EQ(nullptr, method);
251 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
252 : "name == null");
253 method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
254 EXPECT_EQ(nullptr, method);
255 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
256 : "sig == null");
257
258 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
259 }
260
261 void GetFromReflectedField_ToReflectedFieldBadArgumentTest(bool check_jni) {
262 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
263 CheckJniAbortCatcher check_jni_abort_catcher;
264
265 jclass c = env_->FindClass("java/lang/String");
266 ASSERT_NE(c, nullptr);
267 jfieldID fid = env_->GetFieldID(c, "count", "I");
268 ASSERT_NE(fid, nullptr);
269
270 // Check class argument for null argument, not checked in non-check JNI.
271 jobject field = env_->ToReflectedField(nullptr, fid, JNI_FALSE);
272 if (check_jni) {
273 EXPECT_EQ(field, nullptr);
274 check_jni_abort_catcher.Check("ToReflectedField received NULL jclass");
275 } else {
276 EXPECT_NE(field, nullptr);
277 }
278
279 field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
280 EXPECT_EQ(field, nullptr);
281 check_jni_abort_catcher.Check(check_jni ? "jfieldID was NULL"
282 : "fid == null");
283
284 fid = env_->FromReflectedField(nullptr);
285 ASSERT_EQ(fid, nullptr);
286 check_jni_abort_catcher.Check(check_jni ? "expected non-null java.lang.reflect.Field"
287 : "jlr_field == null");
288
289 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
290 }
291
292 void GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(bool check_jni) {
293 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
294 CheckJniAbortCatcher check_jni_abort_catcher;
295
296 jclass c = env_->FindClass("java/lang/String");
297 ASSERT_NE(c, nullptr);
298 jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
299 ASSERT_NE(mid, nullptr);
300
301 // Check class argument for null argument, not checked in non-check JNI.
302 jobject method = env_->ToReflectedMethod(nullptr, mid, JNI_FALSE);
303 if (check_jni) {
304 EXPECT_EQ(method, nullptr);
305 check_jni_abort_catcher.Check("ToReflectedMethod received NULL jclass");
306 } else {
307 EXPECT_NE(method, nullptr);
308 }
309
310 method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
311 EXPECT_EQ(method, nullptr);
312 check_jni_abort_catcher.Check(check_jni ? "jmethodID was NULL"
313 : "mid == null");
314 mid = env_->FromReflectedMethod(method);
315 ASSERT_EQ(mid, nullptr);
316 check_jni_abort_catcher.Check(check_jni ? "expected non-null method" : "jlr_method == null");
317
318 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
319 }
320
321 void RegisterAndUnregisterNativesBadArguments(bool check_jni,
322 CheckJniAbortCatcher* check_jni_abort_catcher) {
323 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
324 // Passing a class of null is a failure.
325 {
326 JNINativeMethod methods[] = { };
327 EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
328 check_jni_abort_catcher->Check(check_jni ? "RegisterNatives received NULL jclass"
329 : "java_class == null");
330 }
331
332 // Passing methods as null is a failure.
333 jclass jlobject = env_->FindClass("java/lang/Object");
334 EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
335 check_jni_abort_catcher->Check("methods == null");
336
337 // Unregisters null is a failure.
338 EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
339 check_jni_abort_catcher->Check(check_jni ? "UnregisterNatives received NULL jclass"
340 : "java_class == null");
341
342 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
343 }
344
345
346 void GetPrimitiveArrayElementsOfWrongType(bool check_jni) {
347 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
348 CheckJniAbortCatcher jni_abort_catcher;
349
350 jbooleanArray array = env_->NewBooleanArray(10);
351 jboolean is_copy;
352 EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
353 jni_abort_catcher.Check(
354 check_jni ? "incompatible array type boolean[] expected byte[]"
355 : "attempt to get byte primitive array elements with an object of type boolean[]");
356 EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
357 jni_abort_catcher.Check(
358 check_jni ? "incompatible array type boolean[] expected short[]"
359 : "attempt to get short primitive array elements with an object of type boolean[]");
360 EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
361 jni_abort_catcher.Check(
362 check_jni ? "incompatible array type boolean[] expected char[]"
363 : "attempt to get char primitive array elements with an object of type boolean[]");
364 EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
365 jni_abort_catcher.Check(
366 check_jni ? "incompatible array type boolean[] expected int[]"
367 : "attempt to get int primitive array elements with an object of type boolean[]");
368 EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
369 jni_abort_catcher.Check(
370 check_jni ? "incompatible array type boolean[] expected long[]"
371 : "attempt to get long primitive array elements with an object of type boolean[]");
372 EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
373 jni_abort_catcher.Check(
374 check_jni ? "incompatible array type boolean[] expected float[]"
375 : "attempt to get float primitive array elements with an object of type boolean[]");
376 EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
377 jni_abort_catcher.Check(
378 check_jni ? "incompatible array type boolean[] expected double[]"
379 : "attempt to get double primitive array elements with an object of type boolean[]");
380 jbyteArray array2 = env_->NewByteArray(10);
381 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy),
382 nullptr);
383 jni_abort_catcher.Check(
384 check_jni ? "incompatible array type byte[] expected boolean[]"
385 : "attempt to get boolean primitive array elements with an object of type byte[]");
386 jobject object = env_->NewStringUTF("Test String");
387 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy),
388 nullptr);
389 jni_abort_catcher.Check(
390 check_jni ? "jarray argument has non-array type: java.lang.String"
391 : "attempt to get boolean primitive array elements with an object of type java.lang.String");
392
393 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
394 }
395
396 void ReleasePrimitiveArrayElementsOfWrongType(bool check_jni) {
397 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
398 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogersdd11d2a2014-11-19 10:06:46 -0800399 {
400 jbooleanArray array = env_->NewBooleanArray(10);
401 ASSERT_TRUE(array != nullptr);
402 jboolean is_copy;
403 jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
404 ASSERT_TRUE(elements != nullptr);
405 env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
406 reinterpret_cast<jbyte*>(elements), 0);
407 jni_abort_catcher.Check(
408 check_jni ? "incompatible array type boolean[] expected byte[]"
409 : "attempt to release byte primitive array elements with an object of type boolean[]");
410 env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
411 reinterpret_cast<jshort*>(elements), 0);
412 jni_abort_catcher.Check(
413 check_jni ? "incompatible array type boolean[] expected short[]"
414 : "attempt to release short primitive array elements with an object of type boolean[]");
415 env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
416 reinterpret_cast<jchar*>(elements), 0);
417 jni_abort_catcher.Check(
418 check_jni ? "incompatible array type boolean[] expected char[]"
419 : "attempt to release char primitive array elements with an object of type boolean[]");
420 env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
421 reinterpret_cast<jint*>(elements), 0);
422 jni_abort_catcher.Check(
423 check_jni ? "incompatible array type boolean[] expected int[]"
424 : "attempt to release int primitive array elements with an object of type boolean[]");
425 env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
426 reinterpret_cast<jlong*>(elements), 0);
427 jni_abort_catcher.Check(
428 check_jni ? "incompatible array type boolean[] expected long[]"
429 : "attempt to release long primitive array elements with an object of type boolean[]");
430 env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
431 reinterpret_cast<jfloat*>(elements), 0);
432 jni_abort_catcher.Check(
433 check_jni ? "incompatible array type boolean[] expected float[]"
434 : "attempt to release float primitive array elements with an object of type boolean[]");
435 env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
436 reinterpret_cast<jdouble*>(elements), 0);
437 jni_abort_catcher.Check(
438 check_jni ? "incompatible array type boolean[] expected double[]"
439 : "attempt to release double primitive array elements with an object of type boolean[]");
Ian Rogers68d8b422014-07-17 11:09:10 -0700440
Ian Rogersdd11d2a2014-11-19 10:06:46 -0800441 // Don't leak the elements array.
442 env_->ReleaseBooleanArrayElements(array, elements, 0);
443 }
444 {
445 jbyteArray array = env_->NewByteArray(10);
446 jboolean is_copy;
447 jbyte* elements = env_->GetByteArrayElements(array, &is_copy);
448
449 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array),
450 reinterpret_cast<jboolean*>(elements), 0);
451 jni_abort_catcher.Check(
452 check_jni ? "incompatible array type byte[] expected boolean[]"
453 : "attempt to release boolean primitive array elements with an object of type byte[]");
454 jobject object = env_->NewStringUTF("Test String");
455 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object),
456 reinterpret_cast<jboolean*>(elements), 0);
457 jni_abort_catcher.Check(
458 check_jni ? "jarray argument has non-array type: java.lang.String"
459 : "attempt to release boolean primitive array elements with an object of type "
Ian Rogers68d8b422014-07-17 11:09:10 -0700460 "java.lang.String");
461
Ian Rogersdd11d2a2014-11-19 10:06:46 -0800462 // Don't leak the elements array.
463 env_->ReleaseByteArrayElements(array, elements, 0);
464 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700465 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
466 }
467
468 void GetReleasePrimitiveArrayCriticalOfWrongType(bool check_jni) {
469 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
470 CheckJniAbortCatcher jni_abort_catcher;
471
472 jobject object = env_->NewStringUTF("Test String");
473 jboolean is_copy;
474 void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
475 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
476 : "expected primitive array, given java.lang.String");
477 env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
478 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
479 : "expected primitive array, given java.lang.String");
480
481 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
482 }
483
484 void GetPrimitiveArrayRegionElementsOfWrongType(bool check_jni) {
485 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
486 CheckJniAbortCatcher jni_abort_catcher;
487 constexpr size_t kLength = 10;
488 jbooleanArray array = env_->NewBooleanArray(kLength);
489 ASSERT_TRUE(array != nullptr);
490 jboolean elements[kLength];
491 env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
492 reinterpret_cast<jbyte*>(elements));
493 jni_abort_catcher.Check(
494 check_jni ? "incompatible array type boolean[] expected byte[]"
495 : "attempt to get region of byte primitive array elements with an object of type boolean[]");
496 env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
497 reinterpret_cast<jshort*>(elements));
498 jni_abort_catcher.Check(
499 check_jni ? "incompatible array type boolean[] expected short[]"
500 : "attempt to get region of short primitive array elements with an object of type boolean[]");
501 env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
502 reinterpret_cast<jchar*>(elements));
503 jni_abort_catcher.Check(
504 check_jni ? "incompatible array type boolean[] expected char[]"
505 : "attempt to get region of char primitive array elements with an object of type boolean[]");
506 env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
507 reinterpret_cast<jint*>(elements));
508 jni_abort_catcher.Check(
509 check_jni ? "incompatible array type boolean[] expected int[]"
510 : "attempt to get region of int primitive array elements with an object of type boolean[]");
511 env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
512 reinterpret_cast<jlong*>(elements));
513 jni_abort_catcher.Check(
514 check_jni ? "incompatible array type boolean[] expected long[]"
515 : "attempt to get region of long primitive array elements with an object of type boolean[]");
516 env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
517 reinterpret_cast<jfloat*>(elements));
518 jni_abort_catcher.Check(
519 check_jni ? "incompatible array type boolean[] expected float[]"
520 : "attempt to get region of float primitive array elements with an object of type boolean[]");
521 env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
522 reinterpret_cast<jdouble*>(elements));
523 jni_abort_catcher.Check(
524 check_jni ? "incompatible array type boolean[] expected double[]"
525 : "attempt to get region of double primitive array elements with an object of type boolean[]");
526 jbyteArray array2 = env_->NewByteArray(10);
527 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
528 reinterpret_cast<jboolean*>(elements));
529 jni_abort_catcher.Check(
530 check_jni ? "incompatible array type byte[] expected boolean[]"
531 : "attempt to get region of boolean primitive array elements with an object of type byte[]");
532 jobject object = env_->NewStringUTF("Test String");
533 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
534 reinterpret_cast<jboolean*>(elements));
535 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
536 : "attempt to get region of boolean primitive array elements with an object of type "
537 "java.lang.String");
538
539 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
540 }
541
542 void SetPrimitiveArrayRegionElementsOfWrongType(bool check_jni) {
543 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
544 CheckJniAbortCatcher jni_abort_catcher;
545 constexpr size_t kLength = 10;
546 jbooleanArray array = env_->NewBooleanArray(kLength);
547 ASSERT_TRUE(array != nullptr);
548 jboolean elements[kLength];
549 env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
550 reinterpret_cast<jbyte*>(elements));
551 jni_abort_catcher.Check(
552 check_jni ? "incompatible array type boolean[] expected byte[]"
553 : "attempt to set region of byte primitive array elements with an object of type boolean[]");
554 env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
555 reinterpret_cast<jshort*>(elements));
556 jni_abort_catcher.Check(
557 check_jni ? "incompatible array type boolean[] expected short[]"
558 : "attempt to set region of short primitive array elements with an object of type boolean[]");
559 env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
560 reinterpret_cast<jchar*>(elements));
561 jni_abort_catcher.Check(
562 check_jni ? "incompatible array type boolean[] expected char[]"
563 : "attempt to set region of char primitive array elements with an object of type boolean[]");
564 env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
565 reinterpret_cast<jint*>(elements));
566 jni_abort_catcher.Check(
567 check_jni ? "incompatible array type boolean[] expected int[]"
568 : "attempt to set region of int primitive array elements with an object of type boolean[]");
569 env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
570 reinterpret_cast<jlong*>(elements));
571 jni_abort_catcher.Check(
572 check_jni ? "incompatible array type boolean[] expected long[]"
573 : "attempt to set region of long primitive array elements with an object of type boolean[]");
574 env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
575 reinterpret_cast<jfloat*>(elements));
576 jni_abort_catcher.Check(
577 check_jni ? "incompatible array type boolean[] expected float[]"
578 : "attempt to set region of float primitive array elements with an object of type boolean[]");
579 env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
580 reinterpret_cast<jdouble*>(elements));
581 jni_abort_catcher.Check(
582 check_jni ? "incompatible array type boolean[] expected double[]"
583 : "attempt to set region of double primitive array elements with an object of type boolean[]");
584 jbyteArray array2 = env_->NewByteArray(10);
585 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
586 reinterpret_cast<jboolean*>(elements));
587 jni_abort_catcher.Check(
588 check_jni ? "incompatible array type byte[] expected boolean[]"
589 : "attempt to set region of boolean primitive array elements with an object of type byte[]");
590 jobject object = env_->NewStringUTF("Test String");
591 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
592 reinterpret_cast<jboolean*>(elements));
593 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
594 : "attempt to set region of boolean primitive array elements with an object of type "
595 "java.lang.String");
596 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
597 }
598
599 void NewObjectArrayBadArguments(bool check_jni) {
600 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
601 CheckJniAbortCatcher jni_abort_catcher;
602
603 jclass element_class = env_->FindClass("java/lang/String");
604 ASSERT_NE(element_class, nullptr);
605
606 env_->NewObjectArray(-1, element_class, nullptr);
607 jni_abort_catcher.Check(check_jni ? "negative jsize: -1" : "negative array length: -1");
608
609 env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr);
610 jni_abort_catcher.Check(check_jni ? "negative jsize: -2147483648"
611 : "negative array length: -2147483648");
612
613 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
614 }
615
Andreas Gampe5f4a09a2015-09-28 13:16:33 -0700616 void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
617 void* native_fnptr) {
618 // Initialize class loader and set generic JNI entrypoint.
619 // Note: this code is adapted from the jni_compiler_test, and taken with minimal modifications.
620 if (!runtime_->IsStarted()) {
621 {
622 ScopedObjectAccess soa(Thread::Current());
623 class_loader_ = LoadDex("MyClassNatives");
624 StackHandleScope<1> hs(soa.Self());
625 Handle<mirror::ClassLoader> loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700626 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_)));
Andreas Gampe5f4a09a2015-09-28 13:16:33 -0700627 mirror::Class* c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
628 const auto pointer_size = class_linker_->GetImagePointerSize();
Vladimir Markoba118822017-06-12 15:41:56 +0100629 ArtMethod* method = c->FindClassMethod(method_name, method_sig, pointer_size);
Andreas Gampe5f4a09a2015-09-28 13:16:33 -0700630 ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig;
Vladimir Markoba118822017-06-12 15:41:56 +0100631 ASSERT_EQ(direct, method->IsDirect());
Andreas Gampe5f4a09a2015-09-28 13:16:33 -0700632 method->SetEntryPointFromQuickCompiledCode(class_linker_->GetRuntimeQuickGenericJniStub());
633 }
634 // Start runtime.
635 Thread::Current()->TransitionFromSuspendedToRunnable();
636 bool started = runtime_->Start();
637 CHECK(started);
638 }
639 // JNI operations after runtime start.
640 env_ = Thread::Current()->GetJniEnv();
641 jklass_ = env_->FindClass("MyClassNatives");
642 ASSERT_TRUE(jklass_ != nullptr) << method_name << " " << method_sig;
643
644 if (direct) {
645 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
646 } else {
647 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
648 }
649 ASSERT_TRUE(jmethod_ != nullptr) << method_name << " " << method_sig;
650
651 if (native_fnptr != nullptr) {
652 JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
653 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
654 << method_name << " " << method_sig;
655 } else {
656 env_->UnregisterNatives(jklass_);
657 }
658
659 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
660 jobj_ = env_->NewObject(jklass_, constructor);
661 ASSERT_TRUE(jobj_ != nullptr) << method_name << " " << method_sig;
662 }
663
Elliott Hughesa2501992011-08-26 19:39:54 -0700664 JavaVMExt* vm_;
Brian Carlstrom4d571432012-05-16 00:21:41 -0700665 JNIEnv* env_;
Elliott Hughes814e4032011-08-23 12:07:56 -0700666 jclass aioobe_;
Elliott Hughesb264f082012-04-06 17:10:10 -0700667 jclass ase_;
Elliott Hughesb465ab02011-08-24 11:21:21 -0700668 jclass sioobe_;
Andreas Gampe5f4a09a2015-09-28 13:16:33 -0700669
670 jclass jklass_;
671 jobject jobj_;
672 jobject class_loader_;
673 jmethodID jmethod_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700674};
675
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700676TEST_F(JniInternalTest, AllocObject) {
677 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700678 ASSERT_NE(c, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700679 jobject o = env_->AllocObject(c);
Ian Rogers2d10b202014-05-12 19:15:18 -0700680 ASSERT_NE(o, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700681
682 // We have an instance of the class we asked for...
683 ASSERT_TRUE(env_->IsInstanceOf(o, c));
684 // ...whose fields haven't been initialized because
685 // we didn't call a constructor.
Vladimir Markofdaf0f42016-10-13 19:29:53 +0100686 // Even with string compression empty string has `count == 0`.
687 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700688}
689
Elliott Hughesc7ac37f2011-08-12 12:21:58 -0700690TEST_F(JniInternalTest, GetVersion) {
691 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
692}
693
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700694TEST_F(JniInternalTest, FindClass) {
Andreas Gampe369810a2015-01-14 19:53:31 -0800695 // This tests leads to warnings in the log.
696 ScopedLogSeverity sls(LogSeverity::ERROR);
697
Ian Rogers68d8b422014-07-17 11:09:10 -0700698 FindClassTest(false);
699 FindClassTest(true);
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700700}
701
Elliott Hughescdf53122011-08-19 15:46:09 -0700702TEST_F(JniInternalTest, GetFieldID) {
703 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
Ian Rogers2d10b202014-05-12 19:15:18 -0700704 ASSERT_NE(jlnsfe, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700705 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700706 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700707
708 // Wrong type.
709 jfieldID fid = env_->GetFieldID(c, "count", "J");
Ian Rogers2d10b202014-05-12 19:15:18 -0700710 EXPECT_EQ(nullptr, fid);
711 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700712
Ian Rogersb17d08b2011-09-02 16:16:49 -0700713 // Wrong type where type doesn't exist.
714 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700715 EXPECT_EQ(nullptr, fid);
716 ExpectException(jlnsfe);
Ian Rogersb17d08b2011-09-02 16:16:49 -0700717
Elliott Hughescdf53122011-08-19 15:46:09 -0700718 // Wrong name.
719 fid = env_->GetFieldID(c, "Count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700720 EXPECT_EQ(nullptr, fid);
721 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700722
723 // Good declared field lookup.
724 fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700725 EXPECT_NE(nullptr, fid);
Elliott Hughescdf53122011-08-19 15:46:09 -0700726 EXPECT_FALSE(env_->ExceptionCheck());
727
728 // Good superclass field lookup.
729 c = env_->FindClass("java/lang/StringBuilder");
730 fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700731 EXPECT_NE(nullptr, fid);
732 EXPECT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700733 EXPECT_FALSE(env_->ExceptionCheck());
734
735 // Not instance.
736 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700737 EXPECT_EQ(nullptr, fid);
738 ExpectException(jlnsfe);
739
740 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -0700741 GetFieldIdBadArgumentTest(false);
742 GetFieldIdBadArgumentTest(true);
Elliott Hughescdf53122011-08-19 15:46:09 -0700743}
744
745TEST_F(JniInternalTest, GetStaticFieldID) {
746 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
Ian Rogers2d10b202014-05-12 19:15:18 -0700747 ASSERT_NE(jlnsfe, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700748 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700749 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700750
751 // Wrong type.
752 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
Ian Rogers2d10b202014-05-12 19:15:18 -0700753 EXPECT_EQ(nullptr, fid);
754 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700755
Ian Rogersb17d08b2011-09-02 16:16:49 -0700756 // Wrong type where type doesn't exist.
757 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700758 EXPECT_EQ(nullptr, fid);
759 ExpectException(jlnsfe);
Ian Rogersb17d08b2011-09-02 16:16:49 -0700760
Elliott Hughescdf53122011-08-19 15:46:09 -0700761 // Wrong name.
762 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700763 EXPECT_EQ(nullptr, fid);
764 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700765
766 // Good declared field lookup.
767 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700768 EXPECT_NE(nullptr, fid);
769 EXPECT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700770 EXPECT_FALSE(env_->ExceptionCheck());
771
772 // Not static.
773 fid = env_->GetStaticFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700774 EXPECT_EQ(nullptr, fid);
775 ExpectException(jlnsfe);
776
777 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -0700778 GetStaticFieldIdBadArgumentTest(false);
779 GetStaticFieldIdBadArgumentTest(true);
Elliott Hughescdf53122011-08-19 15:46:09 -0700780}
781
Ian Rogers4dd71f12011-08-16 14:16:02 -0700782TEST_F(JniInternalTest, GetMethodID) {
783 jclass jlobject = env_->FindClass("java/lang/Object");
784 jclass jlstring = env_->FindClass("java/lang/String");
785 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
Brian Carlstrom004644f2014-06-18 08:34:01 -0700786 jclass jncrbc = env_->FindClass("java/nio/channels/ReadableByteChannel");
Ian Rogers4dd71f12011-08-16 14:16:02 -0700787
Brian Carlstrom004644f2014-06-18 08:34:01 -0700788 // Sanity check that no exceptions are pending.
Elliott Hughescdf53122011-08-19 15:46:09 -0700789 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700790
791 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
Brian Carlstrom004644f2014-06-18 08:34:01 -0700792 // a pending exception.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700793 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700794 EXPECT_EQ(nullptr, method);
795 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700796
Brian Carlstrom004644f2014-06-18 08:34:01 -0700797 // Check that java.lang.Object.equals() does exist.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700798 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
Ian Rogers2d10b202014-05-12 19:15:18 -0700799 EXPECT_NE(nullptr, method);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700800 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700801
802 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
Brian Carlstrom004644f2014-06-18 08:34:01 -0700803 // method is static.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700804 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700805 EXPECT_EQ(nullptr, method);
806 ExpectException(jlnsme);
Brian Carlstromea46f952013-07-30 01:26:50 -0700807
Brian Carlstrom004644f2014-06-18 08:34:01 -0700808 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor.
Brian Carlstromea46f952013-07-30 01:26:50 -0700809 method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700810 EXPECT_NE(nullptr, method);
Brian Carlstromea46f952013-07-30 01:26:50 -0700811 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers2d10b202014-05-12 19:15:18 -0700812
Brian Carlstrom004644f2014-06-18 08:34:01 -0700813 // Check that GetMethodID can find a interface method inherited from another interface.
814 method = env_->GetMethodID(jncrbc, "close", "()V");
815 EXPECT_NE(nullptr, method);
816 EXPECT_FALSE(env_->ExceptionCheck());
817
Ian Rogers2d10b202014-05-12 19:15:18 -0700818 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -0700819 GetMethodIdBadArgumentTest(false);
820 GetMethodIdBadArgumentTest(true);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700821}
822
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700823TEST_F(JniInternalTest, CallVoidMethodNullReceiver) {
824 jclass jlobject = env_->FindClass("java/lang/Object");
825 jmethodID method;
826
827 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor.
828 method = env_->GetMethodID(jlobject, "<init>", "()V");
829 EXPECT_NE(nullptr, method);
830 EXPECT_FALSE(env_->ExceptionCheck());
831
832 // Null object to CallVoidMethod.
833 CheckJniAbortCatcher check_jni_abort_catcher;
834 env_->CallVoidMethod(nullptr, method);
835 check_jni_abort_catcher.Check("null");
836}
837
Ian Rogers9e937be2018-02-15 17:06:58 -0800838TEST_F(JniInternalTest, CallVarArgMethodBadPrimitive) {
839 // Check that bad primitive values cause check JNI to abort when
840 // passed out-of-range primitive value var args. As var args can't
841 // differentiate type sizes less than an int, and this isn't
842 // corrected by JNI, this helps ensure JNI code is valid.
843#define DoCall(boxed_type, shorty, c_type, bad_value) \
844 { \
845 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
846 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
847 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
848 EXPECT_NE(nullptr, method); \
849 EXPECT_FALSE(env_->ExceptionCheck()); \
850 CheckJniAbortCatcher check_jni_abort_catcher; \
851 env_->CallStaticObjectMethod(prim_class, method, bad_value); \
852 check_jni_abort_catcher.Check("unexpected " #c_type " value: " #bad_value); \
853 }
854
855 DoCall(Boolean, Z, jboolean, 2);
856 DoCall(Byte, B, jbyte, 128);
857 DoCall(Byte, B, jbyte, -129);
858 DoCall(Short, S, jshort, 32768);
859 DoCall(Short, S, jshort, -32769);
860 DoCall(Character, C, jchar, 65536);
861 DoCall(Character, C, jchar, -1);
862#undef DoCall
863}
864
865TEST_F(JniInternalTest, CallJValueMethodBadPrimitive) {
866 // Check that bad primitive values, passed as jvalues, cause check
867 // JNI to abort. Unlike with var args, sizes less than an int should
868 // be truncated or sign extended and not cause an abort except for
869 // jbooleans that are passed as bytes.
870#define DoFailCall(boxed_type, shorty, c_type, bad_value) \
871 { \
872 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
873 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
874 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
875 EXPECT_NE(nullptr, method); \
876 EXPECT_FALSE(env_->ExceptionCheck()); \
877 CheckJniAbortCatcher check_jni_abort_catcher; \
878 jvalue jval; \
879 jval.i = bad_value; \
880 env_->CallStaticObjectMethodA(prim_class, method, &jval); \
881 check_jni_abort_catcher.Check("unexpected " #c_type " value: " #bad_value); \
882 }
883#define DoGoodCall(boxed_type, shorty, c_type, bad_value) \
884 { \
885 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
886 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
887 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
888 EXPECT_NE(nullptr, method); \
889 EXPECT_FALSE(env_->ExceptionCheck()); \
890 jvalue jval; \
891 jval.i = bad_value; \
892 env_->CallStaticObjectMethodA(prim_class, method, &jval); \
893 }
894
895 DoFailCall(Boolean, Z, jboolean, 2);
896 DoGoodCall(Byte, B, jbyte, 128);
897 DoGoodCall(Byte, B, jbyte, -129);
898 DoGoodCall(Short, S, jshort, 32768);
899 DoGoodCall(Short, S, jshort, -32769);
900 DoGoodCall(Character, C, jchar, 65536);
901 DoGoodCall(Character, C, jchar, -1);
902#undef DoCall
903}
904
Ian Rogers4dd71f12011-08-16 14:16:02 -0700905TEST_F(JniInternalTest, GetStaticMethodID) {
906 jclass jlobject = env_->FindClass("java/lang/Object");
907 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
908
909 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700910 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700911
912 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
913 // a pending exception
914 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700915 EXPECT_EQ(nullptr, method);
916 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700917
918 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
919 // the method is not static
920 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
Ian Rogers2d10b202014-05-12 19:15:18 -0700921 EXPECT_EQ(nullptr, method);
922 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700923
924 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700925 jclass jlstring = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700926 method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
927 EXPECT_NE(nullptr, method);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700928 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers2d10b202014-05-12 19:15:18 -0700929
930 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -0700931 GetStaticMethodIdBadArgumentTest(false);
932 GetStaticMethodIdBadArgumentTest(true);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700933}
934
Andreas Gampea8e3b862016-10-17 20:12:52 -0700935static size_t GetLocalsCapacity(JNIEnv* env) {
936 ScopedObjectAccess soa(Thread::Current());
Ian Rogers55256cb2017-12-21 17:07:11 -0800937 return reinterpret_cast<JNIEnvExt*>(env)->GetLocalsCapacity();
Andreas Gampea8e3b862016-10-17 20:12:52 -0700938}
939
Elliott Hughescdf53122011-08-19 15:46:09 -0700940TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
941 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
942 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700943 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700944 jfieldID fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700945 ASSERT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700946 // Turn the fid into a java.lang.reflect.Field...
947 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
Andreas Gampea8e3b862016-10-17 20:12:52 -0700948 size_t capacity_before = GetLocalsCapacity(env_);
949 for (size_t i = 0; i <= 10; ++i) {
Mathieu Chartier41da5962014-11-15 13:07:39 -0800950 // Regression test for b/18396311, ToReflectedField leaking local refs causing a local
951 // reference table overflows with 512 references to ArtField
952 env_->DeleteLocalRef(env_->ToReflectedField(c, fid, JNI_FALSE));
953 }
Andreas Gampea8e3b862016-10-17 20:12:52 -0700954 size_t capacity_after = GetLocalsCapacity(env_);
955 ASSERT_EQ(capacity_before, capacity_after);
956
Ian Rogers2d10b202014-05-12 19:15:18 -0700957 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700958 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
959 // ...and back again.
960 jfieldID fid2 = env_->FromReflectedField(field);
Ian Rogers2d10b202014-05-12 19:15:18 -0700961 ASSERT_NE(fid2, nullptr);
Brian Carlstromea46f952013-07-30 01:26:50 -0700962 // Make sure we can actually use it.
963 jstring s = env_->NewStringUTF("poop");
jessicahandojo3aaa37b2016-07-29 14:46:37 -0700964 if (mirror::kUseStringCompression) {
Vladimir Markofdaf0f42016-10-13 19:29:53 +0100965 ASSERT_EQ(mirror::String::GetFlaggedCount(4, /* compressible */ true),
966 env_->GetIntField(s, fid2));
jessicahandojo3aaa37b2016-07-29 14:46:37 -0700967 // Create incompressible string
968 jstring s_16 = env_->NewStringUTF("\u0444\u0444");
Vladimir Markofdaf0f42016-10-13 19:29:53 +0100969 ASSERT_EQ(mirror::String::GetFlaggedCount(2, /* compressible */ false),
970 env_->GetIntField(s_16, fid2));
jessicahandojo3aaa37b2016-07-29 14:46:37 -0700971 } else {
972 ASSERT_EQ(4, env_->GetIntField(s, fid2));
973 }
Ian Rogers2d10b202014-05-12 19:15:18 -0700974 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -0700975 GetFromReflectedField_ToReflectedFieldBadArgumentTest(false);
976 GetFromReflectedField_ToReflectedFieldBadArgumentTest(true);
Elliott Hughescdf53122011-08-19 15:46:09 -0700977}
978
979TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
980 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
Sebastien Hertzd3333762014-06-26 14:45:07 +0200981 ASSERT_NE(jlrMethod, nullptr);
982 jclass jlrConstructor = env_->FindClass("java/lang/reflect/Constructor");
983 ASSERT_NE(jlrConstructor, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700984 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700985 ASSERT_NE(c, nullptr);
Sebastien Hertzd3333762014-06-26 14:45:07 +0200986
987 jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700988 ASSERT_NE(mid, nullptr);
Sebastien Hertzd3333762014-06-26 14:45:07 +0200989 // Turn the mid into a java.lang.reflect.Constructor...
Elliott Hughescdf53122011-08-19 15:46:09 -0700990 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
Andreas Gampea8e3b862016-10-17 20:12:52 -0700991 size_t capacity_before = GetLocalsCapacity(env_);
992 for (size_t i = 0; i <= 10; ++i) {
Mathieu Chartier41da5962014-11-15 13:07:39 -0800993 // Regression test for b/18396311, ToReflectedMethod leaking local refs causing a local
994 // reference table overflows with 512 references to ArtMethod
995 env_->DeleteLocalRef(env_->ToReflectedMethod(c, mid, JNI_FALSE));
996 }
Andreas Gampea8e3b862016-10-17 20:12:52 -0700997 size_t capacity_after = GetLocalsCapacity(env_);
998 ASSERT_EQ(capacity_before, capacity_after);
Sebastien Hertzd3333762014-06-26 14:45:07 +0200999 ASSERT_NE(method, nullptr);
1000 ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor));
Elliott Hughescdf53122011-08-19 15:46:09 -07001001 // ...and back again.
1002 jmethodID mid2 = env_->FromReflectedMethod(method);
Ian Rogers2d10b202014-05-12 19:15:18 -07001003 ASSERT_NE(mid2, nullptr);
Brian Carlstromea46f952013-07-30 01:26:50 -07001004 // Make sure we can actually use it.
Sebastien Hertzd3333762014-06-26 14:45:07 +02001005 jstring s = reinterpret_cast<jstring>(env_->AllocObject(c));
1006 ASSERT_NE(s, nullptr);
1007 env_->CallVoidMethod(s, mid2);
Jeff Hao39b6c242015-05-19 20:30:23 -07001008 ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck());
Jeff Hao848f70a2014-01-15 13:49:50 -08001009 env_->ExceptionClear();
Sebastien Hertzd3333762014-06-26 14:45:07 +02001010
1011 mid = env_->GetMethodID(c, "length", "()I");
1012 ASSERT_NE(mid, nullptr);
1013 // Turn the mid into a java.lang.reflect.Method...
1014 method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
1015 ASSERT_NE(method, nullptr);
1016 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
1017 // ...and back again.
1018 mid2 = env_->FromReflectedMethod(method);
1019 ASSERT_NE(mid2, nullptr);
1020 // Make sure we can actually use it.
1021 s = env_->NewStringUTF("poop");
1022 ASSERT_NE(s, nullptr);
Ian Rogers5d27faf2014-05-02 17:17:18 -07001023 ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
Ian Rogers2d10b202014-05-12 19:15:18 -07001024
1025 // Bad arguments.
Ian Rogers68d8b422014-07-17 11:09:10 -07001026 GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(false);
1027 GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(true);
Elliott Hughescdf53122011-08-19 15:46:09 -07001028}
1029
Ian Rogers2d10b202014-05-12 19:15:18 -07001030static void BogusMethod() {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001031 // You can't pass null function pointers to RegisterNatives.
Elliott Hughes5174fe62011-08-23 15:12:35 -07001032}
1033
Ian Rogers2d10b202014-05-12 19:15:18 -07001034TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
Ian Rogers4dd71f12011-08-16 14:16:02 -07001035 jclass jlobject = env_->FindClass("java/lang/Object");
1036 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001037 void* native_function = reinterpret_cast<void*>(BogusMethod);
Ian Rogers4dd71f12011-08-16 14:16:02 -07001038
Ian Rogers2d10b202014-05-12 19:15:18 -07001039 // Sanity check that no exceptions are pending.
Elliott Hughescdf53122011-08-19 15:46:09 -07001040 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -07001041
Andreas Gampe369810a2015-01-14 19:53:31 -08001042 // The following can print errors to the log we'd like to ignore.
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001043 {
Andreas Gampe369810a2015-01-14 19:53:31 -08001044 ScopedLogSeverity sls(LogSeverity::FATAL);
1045 // Check that registering method without name causes a NoSuchMethodError.
1046 {
1047 JNINativeMethod methods[] = { { nullptr, "()V", native_function } };
1048 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1049 }
1050 ExpectException(jlnsme);
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001051
Andreas Gampe369810a2015-01-14 19:53:31 -08001052 // Check that registering method without signature causes a NoSuchMethodError.
1053 {
1054 JNINativeMethod methods[] = { { "notify", nullptr, native_function } };
1055 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1056 }
1057 ExpectException(jlnsme);
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001058
Andreas Gampe369810a2015-01-14 19:53:31 -08001059 // Check that registering method without function causes a NoSuchMethodError.
1060 {
1061 JNINativeMethod methods[] = { { "notify", "()V", nullptr } };
1062 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1063 }
1064 ExpectException(jlnsme);
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001065
Andreas Gampe369810a2015-01-14 19:53:31 -08001066 // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
1067 {
1068 JNINativeMethod methods[] = { { "foo", "()V", native_function } };
1069 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1070 }
1071 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -07001072
Andreas Gampe369810a2015-01-14 19:53:31 -08001073 // Check that registering non-native methods causes a NoSuchMethodError.
1074 {
1075 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", native_function } };
1076 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1077 }
1078 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -07001079 }
Ian Rogers4dd71f12011-08-16 14:16:02 -07001080
Ian Rogers2d10b202014-05-12 19:15:18 -07001081 // Check that registering native methods is successful.
Ian Rogers4dd71f12011-08-16 14:16:02 -07001082 {
Sebastien Hertzfa65e842014-07-03 09:39:53 +02001083 JNINativeMethod methods[] = { { "notify", "()V", native_function } };
Ian Rogers2d10b202014-05-12 19:15:18 -07001084 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
1085 }
1086 EXPECT_FALSE(env_->ExceptionCheck());
1087 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
1088
1089 // Check that registering no methods isn't a failure.
1090 {
1091 JNINativeMethod methods[] = { };
1092 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
1093 }
1094 EXPECT_FALSE(env_->ExceptionCheck());
1095 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
1096
1097 // Check that registering a -ve number of methods is a failure.
1098 CheckJniAbortCatcher check_jni_abort_catcher;
1099 for (int i = -10; i < 0; ++i) {
1100 JNINativeMethod methods[] = { };
1101 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
1102 check_jni_abort_catcher.Check("negative method count: ");
Ian Rogers4dd71f12011-08-16 14:16:02 -07001103 }
1104 EXPECT_FALSE(env_->ExceptionCheck());
Elliott Hughes5174fe62011-08-23 15:12:35 -07001105
Ian Rogers2d10b202014-05-12 19:15:18 -07001106 // Unregistering a class with no natives is a warning.
1107 EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
Ian Rogers68d8b422014-07-17 11:09:10 -07001108
1109 RegisterAndUnregisterNativesBadArguments(false, &check_jni_abort_catcher);
1110 RegisterAndUnregisterNativesBadArguments(true, &check_jni_abort_catcher);
Ian Rogers4dd71f12011-08-16 14:16:02 -07001111}
1112
Brian Carlstromea46f952013-07-30 01:26:50 -07001113#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
1114 get_region_fn, \
1115 set_region_fn, \
1116 get_elements_fn, \
1117 release_elements_fn, \
1118 scalar_type, \
1119 expected_class_descriptor) \
Ian Rogers2d10b202014-05-12 19:15:18 -07001120 jsize size = 4; \
1121 \
Ian Rogers1d99e452014-01-02 17:36:41 -08001122 { \
1123 CheckJniAbortCatcher jni_abort_catcher; \
Ian Rogers68d8b422014-07-17 11:09:10 -07001124 down_cast<JNIEnvExt*>(env_)->SetCheckJniEnabled(false); \
Ian Rogers1d99e452014-01-02 17:36:41 -08001125 /* Allocate an negative sized array and check it has the right failure type. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001126 EXPECT_EQ(env_->new_fn(-1), nullptr); \
Ian Rogers1d99e452014-01-02 17:36:41 -08001127 jni_abort_catcher.Check("negative array length: -1"); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001128 EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
Ian Rogers1d99e452014-01-02 17:36:41 -08001129 jni_abort_catcher.Check("negative array length: -2147483648"); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001130 /* Pass the array as null. */ \
1131 EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
1132 jni_abort_catcher.Check("java_array == null"); \
1133 env_->get_region_fn(nullptr, 0, 0, nullptr); \
1134 jni_abort_catcher.Check("java_array == null"); \
1135 env_->set_region_fn(nullptr, 0, 0, nullptr); \
1136 jni_abort_catcher.Check("java_array == null"); \
1137 env_->get_elements_fn(nullptr, nullptr); \
1138 jni_abort_catcher.Check("java_array == null"); \
1139 env_->release_elements_fn(nullptr, nullptr, 0); \
1140 jni_abort_catcher.Check("java_array == null"); \
1141 /* Pass the elements for region as null. */ \
1142 scalar_type ## Array a = env_->new_fn(size); \
1143 env_->get_region_fn(a, 0, size, nullptr); \
1144 jni_abort_catcher.Check("buf == null"); \
1145 env_->set_region_fn(a, 0, size, nullptr); \
1146 jni_abort_catcher.Check("buf == null"); \
Ian Rogers68d8b422014-07-17 11:09:10 -07001147 down_cast<JNIEnvExt*>(env_)->SetCheckJniEnabled(true); \
Ian Rogers1d99e452014-01-02 17:36:41 -08001148 } \
Elliott Hughes814e4032011-08-23 12:07:56 -07001149 /* Allocate an array and check it has the right type and length. */ \
1150 scalar_type ## Array a = env_->new_fn(size); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001151 EXPECT_NE(a, nullptr); \
Elliott Hughes814e4032011-08-23 12:07:56 -07001152 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
1153 EXPECT_EQ(size, env_->GetArrayLength(a)); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001154 \
1155 /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
Elliott Hughes814e4032011-08-23 12:07:56 -07001156 /* AIOOBE for negative start offset. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001157 env_->get_region_fn(a, -1, 1, nullptr); \
1158 ExpectException(aioobe_); \
1159 env_->set_region_fn(a, -1, 1, nullptr); \
1160 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001161 \
Elliott Hughes814e4032011-08-23 12:07:56 -07001162 /* AIOOBE for negative length. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001163 env_->get_region_fn(a, 0, -1, nullptr); \
1164 ExpectException(aioobe_); \
1165 env_->set_region_fn(a, 0, -1, nullptr); \
1166 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001167 \
Elliott Hughes814e4032011-08-23 12:07:56 -07001168 /* AIOOBE for buffer overrun. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001169 env_->get_region_fn(a, size - 1, size, nullptr); \
1170 ExpectException(aioobe_); \
1171 env_->set_region_fn(a, size - 1, size, nullptr); \
1172 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001173 \
Vladimir Marko795e3412015-11-06 16:57:03 +00001174 /* Regression test against integer overflow in range check. */ \
1175 env_->get_region_fn(a, 0x7fffffff, 0x7fffffff, nullptr); \
1176 ExpectException(aioobe_); \
1177 env_->set_region_fn(a, 0x7fffffff, 0x7fffffff, nullptr); \
1178 ExpectException(aioobe_); \
1179 \
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001180 /* It's okay for the buffer to be null as long as the length is 0. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001181 env_->get_region_fn(a, 2, 0, nullptr); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001182 /* Even if the offset is invalid... */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001183 env_->get_region_fn(a, 123, 0, nullptr); \
1184 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001185 \
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001186 /* It's okay for the buffer to be null as long as the length is 0. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001187 env_->set_region_fn(a, 2, 0, nullptr); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001188 /* Even if the offset is invalid... */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001189 env_->set_region_fn(a, 123, 0, nullptr); \
1190 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001191 \
Elliott Hughes814e4032011-08-23 12:07:56 -07001192 /* Prepare a couple of buffers. */ \
Chih-Hung Hsieh1a0de6a2016-08-26 15:06:11 -07001193 /* NOLINT, no parentheses around scalar_type. */ \
1194 std::unique_ptr<scalar_type[]> src_buf(new scalar_type[size]); /* NOLINT */ \
1195 std::unique_ptr<scalar_type[]> dst_buf(new scalar_type[size]); /* NOLINT */ \
Elliott Hughes814e4032011-08-23 12:07:56 -07001196 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
1197 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001198 \
Elliott Hughes814e4032011-08-23 12:07:56 -07001199 /* Copy all of src_buf onto the heap. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -07001200 env_->set_region_fn(a, 0, size, &src_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -07001201 /* Copy back only part. */ \
1202 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -07001203 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1204 << "short copy equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -07001205 /* Copy the missing pieces. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -07001206 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -07001207 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -07001208 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1209 << "fixed copy not equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -07001210 /* Copy back the whole array. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -07001211 env_->get_region_fn(a, 0, size, &dst_buf[0]); \
Brian Carlstromea46f952013-07-30 01:26:50 -07001212 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1213 << "full copy not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -07001214 /* GetPrimitiveArrayCritical */ \
Ian Rogers2d10b202014-05-12 19:15:18 -07001215 void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
Brian Carlstromea46f952013-07-30 01:26:50 -07001216 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
1217 << "GetPrimitiveArrayCritical not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -07001218 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
1219 /* GetXArrayElements */ \
Chih-Hung Hsieh1a0de6a2016-08-26 15:06:11 -07001220 scalar_type* xs = env_->get_elements_fn(a, nullptr); /* NOLINT, scalar_type */ \
Brian Carlstromea46f952013-07-30 01:26:50 -07001221 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
1222 << # get_elements_fn " not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -07001223 env_->release_elements_fn(a, xs, 0); \
Elliott Hughesbd935992011-08-22 11:59:34 -07001224
Elliott Hughes814e4032011-08-23 12:07:56 -07001225TEST_F(JniInternalTest, BooleanArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001226 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
1227 GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
Elliott Hughes814e4032011-08-23 12:07:56 -07001228}
1229TEST_F(JniInternalTest, ByteArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001230 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
1231 GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
Elliott Hughes814e4032011-08-23 12:07:56 -07001232}
1233TEST_F(JniInternalTest, CharArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001234 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
1235 GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
Elliott Hughes814e4032011-08-23 12:07:56 -07001236}
1237TEST_F(JniInternalTest, DoubleArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001238 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
1239 GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
Elliott Hughes814e4032011-08-23 12:07:56 -07001240}
1241TEST_F(JniInternalTest, FloatArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001242 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
1243 GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
Elliott Hughes814e4032011-08-23 12:07:56 -07001244}
1245TEST_F(JniInternalTest, IntArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001246 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
1247 GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
Elliott Hughes814e4032011-08-23 12:07:56 -07001248}
1249TEST_F(JniInternalTest, LongArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001250 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
1251 GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
Elliott Hughes814e4032011-08-23 12:07:56 -07001252}
1253TEST_F(JniInternalTest, ShortArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -07001254 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
1255 GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
Elliott Hughesd8ddfd52011-08-15 14:32:53 -07001256}
1257
Ian Rogers2d10b202014-05-12 19:15:18 -07001258TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001259 GetPrimitiveArrayElementsOfWrongType(false);
1260 GetPrimitiveArrayElementsOfWrongType(true);
Ian Rogers2d10b202014-05-12 19:15:18 -07001261}
1262
1263TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001264 ReleasePrimitiveArrayElementsOfWrongType(false);
1265 ReleasePrimitiveArrayElementsOfWrongType(true);
Ian Rogers2d10b202014-05-12 19:15:18 -07001266}
Ian Rogers68d8b422014-07-17 11:09:10 -07001267
Ian Rogers2d10b202014-05-12 19:15:18 -07001268TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001269 GetReleasePrimitiveArrayCriticalOfWrongType(false);
1270 GetReleasePrimitiveArrayCriticalOfWrongType(true);
Ian Rogers2d10b202014-05-12 19:15:18 -07001271}
1272
1273TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001274 GetPrimitiveArrayRegionElementsOfWrongType(false);
1275 GetPrimitiveArrayRegionElementsOfWrongType(true);
Ian Rogers2d10b202014-05-12 19:15:18 -07001276}
1277
1278TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001279 SetPrimitiveArrayRegionElementsOfWrongType(false);
1280 SetPrimitiveArrayRegionElementsOfWrongType(true);
Ian Rogers2d10b202014-05-12 19:15:18 -07001281}
1282
Elliott Hughesf2682d52011-08-15 16:37:04 -07001283TEST_F(JniInternalTest, NewObjectArray) {
Elliott Hughesbd935992011-08-22 11:59:34 -07001284 jclass element_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -07001285 ASSERT_NE(element_class, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -07001286 jclass array_class = env_->FindClass("[Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -07001287 ASSERT_NE(array_class, nullptr);
Elliott Hughesf2682d52011-08-15 16:37:04 -07001288
Ian Rogers1d99e452014-01-02 17:36:41 -08001289 jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
Ian Rogers2d10b202014-05-12 19:15:18 -07001290 EXPECT_NE(a, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -07001291 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1292 EXPECT_EQ(0, env_->GetArrayLength(a));
1293
Ian Rogers1d99e452014-01-02 17:36:41 -08001294 a = env_->NewObjectArray(1, element_class, nullptr);
Ian Rogers2d10b202014-05-12 19:15:18 -07001295 EXPECT_NE(a, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -07001296 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1297 EXPECT_EQ(1, env_->GetArrayLength(a));
Ian Rogers1d99e452014-01-02 17:36:41 -08001298 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
Ian Rogers1d99e452014-01-02 17:36:41 -08001299
Ian Rogers2d10b202014-05-12 19:15:18 -07001300 // Negative array length checks.
Ian Rogers68d8b422014-07-17 11:09:10 -07001301 NewObjectArrayBadArguments(false);
1302 NewObjectArrayBadArguments(true);
Ian Rogers1d99e452014-01-02 17:36:41 -08001303}
1304
1305TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) {
1306 const char* primitive_descriptors = "VZBSCIJFD";
1307 const char* primitive_names[] = {
1308 "void", "boolean", "byte", "short", "char", "int", "long", "float", "double"
1309 };
1310 ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names));
1311
Ian Rogers68d8b422014-07-17 11:09:10 -07001312 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Ian Rogers1d99e452014-01-02 17:36:41 -08001313 CheckJniAbortCatcher jni_abort_catcher;
1314 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001315 env_->NewObjectArray(0, nullptr, nullptr);
1316 jni_abort_catcher.Check("element_jclass == null");
Ian Rogers1d99e452014-01-02 17:36:41 -08001317 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
1318 env_->NewObjectArray(1, primitive_class, nullptr);
1319 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
1320 jni_abort_catcher.Check(error_msg.c_str());
1321 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001322 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1323 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
1324 env_->NewObjectArray(0, nullptr, nullptr);
1325 jni_abort_catcher.Check("NewObjectArray received NULL jclass");
1326 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
1327 env_->NewObjectArray(1, primitive_class, nullptr);
1328 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
1329 jni_abort_catcher.Check(error_msg.c_str());
1330 }
1331 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Ian Rogers1d99e452014-01-02 17:36:41 -08001332}
1333
1334TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
1335 jclass element_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -07001336 ASSERT_NE(element_class, nullptr);
Ian Rogers1d99e452014-01-02 17:36:41 -08001337 jclass array_class = env_->FindClass("[Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -07001338 ASSERT_NE(array_class, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001339
1340 jstring s = env_->NewStringUTF("poop");
Ian Rogers1d99e452014-01-02 17:36:41 -08001341 jobjectArray a = env_->NewObjectArray(2, element_class, s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001342 EXPECT_NE(a, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001343 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1344 EXPECT_EQ(2, env_->GetArrayLength(a));
1345 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
1346 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
Ian Rogers1d99e452014-01-02 17:36:41 -08001347
1348 // Attempt to incorrect create an array of strings with initial value of string arrays.
1349 CheckJniAbortCatcher jni_abort_catcher;
1350 env_->NewObjectArray(2, element_class, a);
1351 jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element "
1352 "type of 'java.lang.String'");
Elliott Hughesbd935992011-08-22 11:59:34 -07001353}
1354
1355TEST_F(JniInternalTest, GetArrayLength) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001356 // Already tested in NewObjectArray/NewPrimitiveArray except for null.
Ian Rogers2f022bd2014-11-11 08:43:05 -08001357 CheckJniAbortCatcher jni_abort_catcher;
1358 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1359 EXPECT_EQ(0, env_->GetArrayLength(nullptr));
1360 jni_abort_catcher.Check("java_array == null");
1361 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1362 EXPECT_EQ(JNI_ERR, env_->GetArrayLength(nullptr));
1363 jni_abort_catcher.Check("jarray was NULL");
1364 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes8a26c5c2011-08-15 18:35:43 -07001365}
1366
Elliott Hughes37f7a402011-08-22 18:56:01 -07001367TEST_F(JniInternalTest, GetObjectClass) {
1368 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -07001369 ASSERT_NE(string_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001370 jclass class_class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -07001371 ASSERT_NE(class_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001372
1373 jstring s = env_->NewStringUTF("poop");
1374 jclass c = env_->GetObjectClass(s);
1375 ASSERT_TRUE(env_->IsSameObject(string_class, c));
1376
1377 jclass c2 = env_->GetObjectClass(c);
1378 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
Ian Rogers2d10b202014-05-12 19:15:18 -07001379
1380 // Null as object should fail.
1381 CheckJniAbortCatcher jni_abort_catcher;
1382 EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
1383 jni_abort_catcher.Check("java_object == null");
Elliott Hughes37f7a402011-08-22 18:56:01 -07001384}
1385
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001386TEST_F(JniInternalTest, GetSuperclass) {
1387 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -07001388 ASSERT_NE(object_class, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001389 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -07001390 ASSERT_NE(string_class, nullptr);
Ian Rogersdc180202012-01-29 14:47:29 -08001391 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
Ian Rogers2d10b202014-05-12 19:15:18 -07001392 ASSERT_NE(runnable_interface, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001393 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
Ian Rogers2d10b202014-05-12 19:15:18 -07001394 ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
Brian Carlstrom08ac9222015-05-22 13:43:00 -07001395 ASSERT_EQ(env_->GetSuperclass(runnable_interface), nullptr);
Ian Rogers2d10b202014-05-12 19:15:18 -07001396
1397 // Null as class should fail.
1398 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07001399 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Ian Rogers2d10b202014-05-12 19:15:18 -07001400 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
1401 jni_abort_catcher.Check("java_class == null");
Ian Rogers68d8b422014-07-17 11:09:10 -07001402 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1403 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
1404 jni_abort_catcher.Check("GetSuperclass received NULL jclass");
1405 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001406}
1407
Elliott Hughes37f7a402011-08-22 18:56:01 -07001408TEST_F(JniInternalTest, IsAssignableFrom) {
1409 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -07001410 ASSERT_NE(object_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001411 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -07001412 ASSERT_NE(string_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001413
Narayan Kamath1268b742014-07-11 19:15:11 +01001414 // A superclass is assignable from an instance of its
1415 // subclass but not vice versa.
1416 ASSERT_TRUE(env_->IsAssignableFrom(string_class, object_class));
1417 ASSERT_FALSE(env_->IsAssignableFrom(object_class, string_class));
1418
1419 jclass charsequence_interface = env_->FindClass("java/lang/CharSequence");
1420 ASSERT_NE(charsequence_interface, nullptr);
1421
1422 // An interface is assignable from an instance of an implementing
1423 // class but not vice versa.
1424 ASSERT_TRUE(env_->IsAssignableFrom(string_class, charsequence_interface));
1425 ASSERT_FALSE(env_->IsAssignableFrom(charsequence_interface, string_class));
1426
1427 // Check that arrays are covariant.
1428 jclass string_array_class = env_->FindClass("[Ljava/lang/String;");
1429 ASSERT_NE(string_array_class, nullptr);
1430 jclass object_array_class = env_->FindClass("[Ljava/lang/Object;");
1431 ASSERT_NE(object_array_class, nullptr);
1432 ASSERT_TRUE(env_->IsAssignableFrom(string_array_class, object_array_class));
1433 ASSERT_FALSE(env_->IsAssignableFrom(object_array_class, string_array_class));
1434
1435 // Primitive types are tested in 004-JniTest.
Ian Rogers2d10b202014-05-12 19:15:18 -07001436
1437 // Null as either class should fail.
1438 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07001439 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Ian Rogers2d10b202014-05-12 19:15:18 -07001440 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
1441 jni_abort_catcher.Check("java_class1 == null");
1442 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
1443 jni_abort_catcher.Check("java_class2 == null");
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1445 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
1446 jni_abort_catcher.Check("IsAssignableFrom received NULL jclass");
1447 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
1448 jni_abort_catcher.Check("IsAssignableFrom received NULL jclass");
1449 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001450}
1451
Elliott Hughesb465ab02011-08-24 11:21:21 -07001452TEST_F(JniInternalTest, GetObjectRefType) {
1453 jclass local = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -07001454 ASSERT_TRUE(local != nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001455 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
1456
1457 jobject global = env_->NewGlobalRef(local);
1458 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
1459
1460 jweak weak_global = env_->NewWeakGlobalRef(local);
1461 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
1462
Andreas Gampea8763072014-12-20 00:08:35 -08001463 {
1464 CheckJniAbortCatcher jni_abort_catcher;
1465 jobject invalid = reinterpret_cast<jobject>(this);
1466 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
1467 jni_abort_catcher.Check("use of invalid jobject");
1468 }
Elliott Hughesb465ab02011-08-24 11:21:21 -07001469
1470 // TODO: invoke a native method and test that its arguments are considered local references.
Ian Rogers2d10b202014-05-12 19:15:18 -07001471
Andreas Gampea8763072014-12-20 00:08:35 -08001472 // Null as pointer should not fail and return invalid-ref. b/18820997
Ian Rogers2d10b202014-05-12 19:15:18 -07001473 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
Andreas Gampea8763072014-12-20 00:08:35 -08001474
1475 // TODO: Null as reference should return the original type.
1476 // This requires running a GC so a non-null object gets freed.
Elliott Hughesb465ab02011-08-24 11:21:21 -07001477}
1478
Mathieu Chartier08599992013-12-20 17:17:55 -08001479TEST_F(JniInternalTest, StaleWeakGlobal) {
1480 jclass java_lang_Class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -07001481 ASSERT_NE(java_lang_Class, nullptr);
1482 jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
1483 ASSERT_NE(local_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -08001484 jweak weak_global = env_->NewWeakGlobalRef(local_ref);
Ian Rogers2d10b202014-05-12 19:15:18 -07001485 ASSERT_NE(weak_global, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -08001486 env_->DeleteLocalRef(local_ref);
Roland Levillainaf290312018-02-27 20:02:17 +00001487 // GC should clear the weak global.
1488 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references */ false);
Mathieu Chartier08599992013-12-20 17:17:55 -08001489 jobject new_global_ref = env_->NewGlobalRef(weak_global);
Ian Rogers2d10b202014-05-12 19:15:18 -07001490 EXPECT_EQ(new_global_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -08001491 jobject new_local_ref = env_->NewLocalRef(weak_global);
Ian Rogers2d10b202014-05-12 19:15:18 -07001492 EXPECT_EQ(new_local_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -08001493}
1494
Elliott Hughes8a26c5c2011-08-15 18:35:43 -07001495TEST_F(JniInternalTest, NewStringUTF) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001496 EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -07001497 jstring s;
1498
1499 s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001500 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -07001501 EXPECT_EQ(0, env_->GetStringLength(s));
1502 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1503 s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001504 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -07001505 EXPECT_EQ(5, env_->GetStringLength(s));
1506 EXPECT_EQ(5, env_->GetStringUTFLength(s));
1507
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001508 // Encoded surrogate pair.
1509 s = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80");
1510 EXPECT_NE(s, nullptr);
1511 EXPECT_EQ(2, env_->GetStringLength(s));
Narayan Kamathe16dad12015-02-13 11:49:22 +00001512
1513 // The surrogate pair gets encoded into a 4 byte UTF sequence..
1514 EXPECT_EQ(4, env_->GetStringUTFLength(s));
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001515 const char* chars = env_->GetStringUTFChars(s, nullptr);
Narayan Kamathe16dad12015-02-13 11:49:22 +00001516 EXPECT_STREQ("\xf0\x90\x90\x80", chars);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001517 env_->ReleaseStringUTFChars(s, chars);
1518
Narayan Kamathe16dad12015-02-13 11:49:22 +00001519 // .. but is stored as is in the utf-16 representation.
1520 const jchar* jchars = env_->GetStringChars(s, nullptr);
1521 EXPECT_EQ(0xd801, jchars[0]);
1522 EXPECT_EQ(0xdc00, jchars[1]);
1523 env_->ReleaseStringChars(s, jchars);
1524
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001525 // 4 byte UTF sequence appended to an encoded surrogate pair.
1526 s = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80 \xf0\x9f\x8f\xa0");
1527 EXPECT_NE(s, nullptr);
Narayan Kamathe16dad12015-02-13 11:49:22 +00001528
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001529 // The 4 byte sequence {0xf0, 0x9f, 0x8f, 0xa0} is converted into a surrogate
Narayan Kamathe16dad12015-02-13 11:49:22 +00001530 // pair {0xd83c, 0xdfe0}.
1531 EXPECT_EQ(5, env_->GetStringLength(s));
1532 jchars = env_->GetStringChars(s, nullptr);
1533 // The first surrogate pair, encoded as such in the input.
1534 EXPECT_EQ(0xd801, jchars[0]);
1535 EXPECT_EQ(0xdc00, jchars[1]);
1536 // The second surrogate pair, from the 4 byte UTF sequence in the input.
1537 EXPECT_EQ(0xd83c, jchars[3]);
1538 EXPECT_EQ(0xdfe0, jchars[4]);
1539 env_->ReleaseStringChars(s, jchars);
1540
1541 EXPECT_EQ(9, env_->GetStringUTFLength(s));
1542 chars = env_->GetStringUTFChars(s, nullptr);
1543 EXPECT_STREQ("\xf0\x90\x90\x80 \xf0\x9f\x8f\xa0", chars);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001544 env_->ReleaseStringUTFChars(s, chars);
1545
1546 // A string with 1, 2, 3 and 4 byte UTF sequences with spaces
1547 // between them
1548 s = env_->NewStringUTF("\x24 \xc2\xa2 \xe2\x82\xac \xf0\x9f\x8f\xa0");
1549 EXPECT_NE(s, nullptr);
1550 EXPECT_EQ(8, env_->GetStringLength(s));
Narayan Kamathe16dad12015-02-13 11:49:22 +00001551 EXPECT_EQ(13, env_->GetStringUTFLength(s));
Elliott Hughesf2682d52011-08-15 16:37:04 -07001552}
1553
Elliott Hughes814e4032011-08-23 12:07:56 -07001554TEST_F(JniInternalTest, NewString) {
Elliott Hughes814e4032011-08-23 12:07:56 -07001555 jchar chars[] = { 'h', 'i' };
1556 jstring s;
1557 s = env_->NewString(chars, 0);
Ian Rogers2d10b202014-05-12 19:15:18 -07001558 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -07001559 EXPECT_EQ(0, env_->GetStringLength(s));
1560 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1561 s = env_->NewString(chars, 2);
Ian Rogers2d10b202014-05-12 19:15:18 -07001562 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -07001563 EXPECT_EQ(2, env_->GetStringLength(s));
1564 EXPECT_EQ(2, env_->GetStringUTFLength(s));
1565
1566 // TODO: check some non-ASCII strings.
1567}
1568
Jesse Wilson25e79a52011-11-18 15:31:58 -05001569TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
Ian Rogers1d99e452014-01-02 17:36:41 -08001570 jstring s = env_->NewString(nullptr, 0);
Ian Rogers2d10b202014-05-12 19:15:18 -07001571 EXPECT_NE(s, nullptr);
Jesse Wilson25e79a52011-11-18 15:31:58 -05001572 EXPECT_EQ(0, env_->GetStringLength(s));
1573}
1574
Ian Rogers1d99e452014-01-02 17:36:41 -08001575TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) {
1576 CheckJniAbortCatcher jni_abort_catcher;
1577 env_->NewString(nullptr, 1);
1578 jni_abort_catcher.Check("chars == null && char_count > 0");
1579}
1580
1581TEST_F(JniInternalTest, NewStringNegativeLength) {
1582 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07001583 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Ian Rogers1d99e452014-01-02 17:36:41 -08001584 env_->NewString(nullptr, -1);
1585 jni_abort_catcher.Check("char_count < 0: -1");
1586 env_->NewString(nullptr, std::numeric_limits<jint>::min());
1587 jni_abort_catcher.Check("char_count < 0: -2147483648");
Ian Rogers68d8b422014-07-17 11:09:10 -07001588 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1589 env_->NewString(nullptr, -1);
1590 jni_abort_catcher.Check("negative jsize: -1");
1591 env_->NewString(nullptr, std::numeric_limits<jint>::min());
1592 jni_abort_catcher.Check("negative jsize: -2147483648");
1593 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Jesse Wilson25e79a52011-11-18 15:31:58 -05001594}
1595
Elliott Hughesb465ab02011-08-24 11:21:21 -07001596TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1597 // Already tested in the NewString/NewStringUTF tests.
1598}
1599
1600TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1601 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001602 ASSERT_TRUE(s != nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001603
Ian Rogers2d10b202014-05-12 19:15:18 -07001604 env_->GetStringRegion(s, -1, 0, nullptr);
1605 ExpectException(sioobe_);
1606 env_->GetStringRegion(s, 0, -1, nullptr);
1607 ExpectException(sioobe_);
1608 env_->GetStringRegion(s, 0, 10, nullptr);
1609 ExpectException(sioobe_);
1610 env_->GetStringRegion(s, 10, 1, nullptr);
1611 ExpectException(sioobe_);
Vladimir Marko795e3412015-11-06 16:57:03 +00001612 // Regression test against integer overflow in range check.
1613 env_->GetStringRegion(s, 0x7fffffff, 0x7fffffff, nullptr);
1614 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001615
1616 jchar chars[4] = { 'x', 'x', 'x', 'x' };
1617 env_->GetStringRegion(s, 1, 2, &chars[1]);
1618 EXPECT_EQ('x', chars[0]);
1619 EXPECT_EQ('e', chars[1]);
1620 EXPECT_EQ('l', chars[2]);
1621 EXPECT_EQ('x', chars[3]);
1622
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001623 // It's okay for the buffer to be null as long as the length is 0.
Ian Rogers2d10b202014-05-12 19:15:18 -07001624 env_->GetStringRegion(s, 2, 0, nullptr);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001625 // Even if the offset is invalid...
Ian Rogers2d10b202014-05-12 19:15:18 -07001626 env_->GetStringRegion(s, 123, 0, nullptr);
1627 ExpectException(sioobe_);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001628
Ian Rogers2d10b202014-05-12 19:15:18 -07001629 env_->GetStringUTFRegion(s, -1, 0, nullptr);
1630 ExpectException(sioobe_);
1631 env_->GetStringUTFRegion(s, 0, -1, nullptr);
1632 ExpectException(sioobe_);
1633 env_->GetStringUTFRegion(s, 0, 10, nullptr);
1634 ExpectException(sioobe_);
1635 env_->GetStringUTFRegion(s, 10, 1, nullptr);
1636 ExpectException(sioobe_);
Vladimir Marko795e3412015-11-06 16:57:03 +00001637 // Regression test against integer overflow in range check.
1638 env_->GetStringUTFRegion(s, 0x7fffffff, 0x7fffffff, nullptr);
1639 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001640
1641 char bytes[4] = { 'x', 'x', 'x', 'x' };
1642 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1643 EXPECT_EQ('x', bytes[0]);
1644 EXPECT_EQ('e', bytes[1]);
1645 EXPECT_EQ('l', bytes[2]);
1646 EXPECT_EQ('x', bytes[3]);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001647
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001648 // It's okay for the buffer to be null as long as the length is 0.
Ian Rogers2d10b202014-05-12 19:15:18 -07001649 env_->GetStringUTFRegion(s, 2, 0, nullptr);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001650 // Even if the offset is invalid...
Ian Rogers2d10b202014-05-12 19:15:18 -07001651 env_->GetStringUTFRegion(s, 123, 0, nullptr);
1652 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001653}
1654
Elliott Hughes75770752011-08-24 17:52:38 -07001655TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001656 // Passing in a null jstring is ignored normally, but caught by -Xcheck:jni.
Ian Rogers68d8b422014-07-17 11:09:10 -07001657 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Elliott Hughesb264f082012-04-06 17:10:10 -07001658 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001659 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers2d10b202014-05-12 19:15:18 -07001660 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001661 }
1662 {
1663 CheckJniAbortCatcher check_jni_abort_catcher;
1664 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1665 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
1666 check_jni_abort_catcher.Check("GetStringUTFChars received NULL jstring");
1667 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughesb264f082012-04-06 17:10:10 -07001668 }
Elliott Hughes75770752011-08-24 17:52:38 -07001669
1670 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001671 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001672
Ian Rogers2d10b202014-05-12 19:15:18 -07001673 const char* utf = env_->GetStringUTFChars(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001674 EXPECT_STREQ("hello", utf);
1675 env_->ReleaseStringUTFChars(s, utf);
1676
1677 jboolean is_copy = JNI_FALSE;
1678 utf = env_->GetStringUTFChars(s, &is_copy);
1679 EXPECT_EQ(JNI_TRUE, is_copy);
1680 EXPECT_STREQ("hello", utf);
1681 env_->ReleaseStringUTFChars(s, utf);
1682}
1683
1684TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1685 jstring s = env_->NewStringUTF("hello");
Fred Shih56890e22014-06-02 11:11:52 -07001686 ScopedObjectAccess soa(env_);
Mathieu Chartier0795f232016-09-27 18:43:30 -07001687 ObjPtr<mirror::String> s_m = soa.Decode<mirror::String>(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001688 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001689
1690 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
Ian Rogers2d10b202014-05-12 19:15:18 -07001691 const jchar* chars = env_->GetStringChars(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001692 EXPECT_EQ(expected[0], chars[0]);
1693 EXPECT_EQ(expected[1], chars[1]);
1694 EXPECT_EQ(expected[2], chars[2]);
1695 EXPECT_EQ(expected[3], chars[3]);
1696 EXPECT_EQ(expected[4], chars[4]);
1697 env_->ReleaseStringChars(s, chars);
1698
1699 jboolean is_copy = JNI_FALSE;
1700 chars = env_->GetStringChars(s, &is_copy);
Jeff Hao848f70a2014-01-15 13:49:50 -08001701 if (Runtime::Current()->GetHeap()->IsMovableObject(s_m)) {
Fred Shih56890e22014-06-02 11:11:52 -07001702 EXPECT_EQ(JNI_TRUE, is_copy);
1703 } else {
1704 EXPECT_EQ(JNI_FALSE, is_copy);
1705 }
Elliott Hughes75770752011-08-24 17:52:38 -07001706 EXPECT_EQ(expected[0], chars[0]);
1707 EXPECT_EQ(expected[1], chars[1]);
1708 EXPECT_EQ(expected[2], chars[2]);
1709 EXPECT_EQ(expected[3], chars[3]);
1710 EXPECT_EQ(expected[4], chars[4]);
1711 env_->ReleaseStringChars(s, chars);
1712}
1713
1714TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1715 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001716 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001717
1718 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
Ian Rogers2d10b202014-05-12 19:15:18 -07001719 const jchar* chars = env_->GetStringCritical(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001720 EXPECT_EQ(expected[0], chars[0]);
1721 EXPECT_EQ(expected[1], chars[1]);
1722 EXPECT_EQ(expected[2], chars[2]);
1723 EXPECT_EQ(expected[3], chars[3]);
1724 EXPECT_EQ(expected[4], chars[4]);
1725 env_->ReleaseStringCritical(s, chars);
1726
Fred Shih56890e22014-06-02 11:11:52 -07001727 jboolean is_copy = JNI_TRUE;
Elliott Hughes75770752011-08-24 17:52:38 -07001728 chars = env_->GetStringCritical(s, &is_copy);
jessicahandojo3aaa37b2016-07-29 14:46:37 -07001729 if (mirror::kUseStringCompression) {
1730 // is_copy has to be JNI_TRUE because "hello" is all-ASCII
1731 EXPECT_EQ(JNI_TRUE, is_copy);
1732 } else {
1733 EXPECT_EQ(JNI_FALSE, is_copy);
1734 }
Elliott Hughes75770752011-08-24 17:52:38 -07001735 EXPECT_EQ(expected[0], chars[0]);
1736 EXPECT_EQ(expected[1], chars[1]);
1737 EXPECT_EQ(expected[2], chars[2]);
1738 EXPECT_EQ(expected[3], chars[3]);
1739 EXPECT_EQ(expected[4], chars[4]);
1740 env_->ReleaseStringCritical(s, chars);
jessicahandojo3aaa37b2016-07-29 14:46:37 -07001741
1742 if (mirror::kUseStringCompression) {
1743 // is_copy has to be JNI_FALSE because "\xed\xa0\x81\xed\xb0\x80" is incompressible
1744 jboolean is_copy_16 = JNI_TRUE;
1745 jstring s_16 = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80");
1746 chars = env_->GetStringCritical(s_16, &is_copy_16);
1747 EXPECT_EQ(2, env_->GetStringLength(s_16));
1748 EXPECT_EQ(4, env_->GetStringUTFLength(s_16));
1749 env_->ReleaseStringCritical(s_16, chars);
1750 }
Elliott Hughes75770752011-08-24 17:52:38 -07001751}
1752
Elliott Hughes814e4032011-08-23 12:07:56 -07001753TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
Elliott Hughesb264f082012-04-06 17:10:10 -07001754 jclass java_lang_Class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -07001755 ASSERT_TRUE(java_lang_Class != nullptr);
Elliott Hughes289da822011-08-16 10:11:20 -07001756
Ian Rogers2d10b202014-05-12 19:15:18 -07001757 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
1758 EXPECT_NE(array, nullptr);
1759 EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07001760 env_->SetObjectArrayElement(array, 0, java_lang_Class);
1761 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001762
1763 // ArrayIndexOutOfBounds for negative index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001764 env_->SetObjectArrayElement(array, -1, java_lang_Class);
Ian Rogers2d10b202014-05-12 19:15:18 -07001765 ExpectException(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001766
1767 // ArrayIndexOutOfBounds for too-large index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001768 env_->SetObjectArrayElement(array, 1, java_lang_Class);
Ian Rogers2d10b202014-05-12 19:15:18 -07001769 ExpectException(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001770
Elliott Hughesb264f082012-04-06 17:10:10 -07001771 // ArrayStoreException thrown for bad types.
1772 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
Ian Rogers2d10b202014-05-12 19:15:18 -07001773 ExpectException(ase_);
1774
1775 // Null as array should fail.
1776 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07001777 bool old_check_jni = vm_->SetCheckJniEnabled(false);
Ian Rogers2d10b202014-05-12 19:15:18 -07001778 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1779 jni_abort_catcher.Check("java_array == null");
1780 env_->SetObjectArrayElement(nullptr, 0, nullptr);
1781 jni_abort_catcher.Check("java_array == null");
Ian Rogers68d8b422014-07-17 11:09:10 -07001782 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1783 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1784 jni_abort_catcher.Check("jarray was NULL");
1785 env_->SetObjectArrayElement(nullptr, 0, nullptr);
1786 jni_abort_catcher.Check("jarray was NULL");
1787 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes289da822011-08-16 10:11:20 -07001788}
1789
Ian Rogers647b1a82014-10-10 11:02:11 -07001790#define EXPECT_STATIC_PRIMITIVE_FIELD(expect_eq, type, field_name, sig, value1, value2) \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001791 do { \
1792 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001793 EXPECT_NE(fid, nullptr); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001794 env_->SetStatic ## type ## Field(c, fid, value1); \
Ian Rogers647b1a82014-10-10 11:02:11 -07001795 expect_eq(value1, env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001796 env_->SetStatic ## type ## Field(c, fid, value2); \
Ian Rogers647b1a82014-10-10 11:02:11 -07001797 expect_eq(value2, env_->GetStatic ## type ## Field(c, fid)); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001798 \
Ian Rogers68d8b422014-07-17 11:09:10 -07001799 bool old_check_jni = vm_->SetCheckJniEnabled(false); \
1800 { \
1801 CheckJniAbortCatcher jni_abort_catcher; \
1802 env_->GetStatic ## type ## Field(nullptr, fid); \
1803 env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1804 } \
Ian Rogers2d10b202014-05-12 19:15:18 -07001805 CheckJniAbortCatcher jni_abort_catcher; \
Ian Rogers2d10b202014-05-12 19:15:18 -07001806 env_->GetStatic ## type ## Field(c, nullptr); \
1807 jni_abort_catcher.Check("fid == null"); \
1808 env_->SetStatic ## type ## Field(c, nullptr, value1); \
1809 jni_abort_catcher.Check("fid == null"); \
Ian Rogers68d8b422014-07-17 11:09:10 -07001810 \
1811 EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); \
1812 env_->GetStatic ## type ## Field(nullptr, fid); \
1813 jni_abort_catcher.Check("received NULL jclass"); \
1814 env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1815 jni_abort_catcher.Check("received NULL jclass"); \
1816 env_->GetStatic ## type ## Field(c, nullptr); \
1817 jni_abort_catcher.Check("jfieldID was NULL"); \
1818 env_->SetStatic ## type ## Field(c, nullptr, value1); \
1819 jni_abort_catcher.Check("jfieldID was NULL"); \
1820 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001821 } while (false)
1822
Ian Rogers647b1a82014-10-10 11:02:11 -07001823#define EXPECT_PRIMITIVE_FIELD(expect_eq, instance, type, field_name, sig, value1, value2) \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001824 do { \
1825 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001826 EXPECT_NE(fid, nullptr); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001827 env_->Set ## type ## Field(instance, fid, value1); \
Ian Rogers647b1a82014-10-10 11:02:11 -07001828 expect_eq(value1, env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001829 env_->Set ## type ## Field(instance, fid, value2); \
Ian Rogers647b1a82014-10-10 11:02:11 -07001830 expect_eq(value2, env_->Get ## type ## Field(instance, fid)); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001831 \
Ian Rogers68d8b422014-07-17 11:09:10 -07001832 bool old_check_jni = vm_->SetCheckJniEnabled(false); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001833 CheckJniAbortCatcher jni_abort_catcher; \
1834 env_->Get ## type ## Field(nullptr, fid); \
1835 jni_abort_catcher.Check("obj == null"); \
1836 env_->Set ## type ## Field(nullptr, fid, value1); \
1837 jni_abort_catcher.Check("obj == null"); \
1838 env_->Get ## type ## Field(instance, nullptr); \
1839 jni_abort_catcher.Check("fid == null"); \
1840 env_->Set ## type ## Field(instance, nullptr, value1); \
1841 jni_abort_catcher.Check("fid == null"); \
Ian Rogers68d8b422014-07-17 11:09:10 -07001842 EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); \
1843 env_->Get ## type ## Field(nullptr, fid); \
1844 jni_abort_catcher.Check("field operation on NULL object:"); \
1845 env_->Set ## type ## Field(nullptr, fid, value1); \
1846 jni_abort_catcher.Check("field operation on NULL object:"); \
1847 env_->Get ## type ## Field(instance, nullptr); \
1848 jni_abort_catcher.Check("jfieldID was NULL"); \
1849 env_->Set ## type ## Field(instance, nullptr, value1); \
1850 jni_abort_catcher.Check("jfieldID was NULL"); \
1851 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001852 } while (false)
1853
Alex Lighte4033fa2017-12-13 10:32:59 -08001854#define TEST_PRIMITIVE_FIELD_FOR_CLASS(cname) \
1855 do { \
1856 Thread::Current()->TransitionFromSuspendedToRunnable(); \
1857 LoadDex("AllFields"); \
1858 bool started = runtime_->Start(); \
1859 ASSERT_TRUE(started); \
1860 jclass c = env_->FindClass(cname); \
1861 ASSERT_NE(c, nullptr); \
1862 jobject o = env_->AllocObject(c); \
1863 ASSERT_NE(o, nullptr); \
1864 \
1865 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE); \
1866 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Byte, "sB", "B", 1, 2); \
1867 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Char, "sC", "C", 'a', 'b'); \
1868 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, Double, "sD", "D", 1.0, 2.0); \
1869 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, Float, "sF", "F", 1.0, 2.0); \
1870 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Int, "sI", "I", 1, 2); \
1871 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Long, "sJ", "J", 1, 2); \
1872 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Short, "sS", "S", 1, 2); \
1873 \
1874 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE); \
1875 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Byte, "iB", "B", 1, 2); \
1876 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Char, "iC", "C", 'a', 'b'); \
1877 EXPECT_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, o, Double, "iD", "D", 1.0, 2.0); \
1878 EXPECT_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, o, Float, "iF", "F", 1.0, 2.0); \
1879 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Int, "iI", "I", 1, 2); \
1880 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Long, "iJ", "J", 1, 2); \
1881 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Short, "iS", "S", 1, 2); \
1882 } while (false)
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001883
1884TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Alex Lighte4033fa2017-12-13 10:32:59 -08001885 TEST_PRIMITIVE_FIELD_FOR_CLASS("AllFields");
1886}
1887
1888TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField_Subclass) {
1889 TEST_PRIMITIVE_FIELD_FOR_CLASS("AllFieldsSub");
1890}
1891
1892#define EXPECT_UNRELATED_FIELD_FAILURE(type, field_name, sig, value1) \
1893 do { \
1894 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1895 EXPECT_NE(fid, nullptr); \
1896 CheckJniAbortCatcher jni_abort_catcher; \
1897 env_->Get ## type ## Field(uc, fid); \
1898 jni_abort_catcher.Check("not valid for an object of class"); \
1899 env_->Set ## type ## Field(uc, fid, value1); \
1900 jni_abort_catcher.Check("not valid for an object of class"); \
1901 } while (false)
1902
1903TEST_F(JniInternalTest, GetField_SetField_unrelated) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001904 Thread::Current()->TransitionFromSuspendedToRunnable();
1905 LoadDex("AllFields");
Brian Carlstrombd86bcc2013-03-10 20:26:16 -07001906 bool started = runtime_->Start();
Ian Rogers2d10b202014-05-12 19:15:18 -07001907 ASSERT_TRUE(started);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001908 jclass c = env_->FindClass("AllFields");
Ian Rogers2d10b202014-05-12 19:15:18 -07001909 ASSERT_NE(c, nullptr);
Alex Lighte4033fa2017-12-13 10:32:59 -08001910 jclass uc = env_->FindClass("AllFieldsUnrelated");
1911 ASSERT_NE(uc, nullptr);
1912 bool old_check_jni = vm_->SetCheckJniEnabled(true);
1913 EXPECT_UNRELATED_FIELD_FAILURE(Boolean, "sZ", "Z", JNI_TRUE);
1914 EXPECT_UNRELATED_FIELD_FAILURE(Byte, "sB", "B", 1);
1915 EXPECT_UNRELATED_FIELD_FAILURE(Char, "sC", "C", 'a');
1916 EXPECT_UNRELATED_FIELD_FAILURE(Double, "sD", "D", 1.0);
1917 EXPECT_UNRELATED_FIELD_FAILURE(Float, "sF", "F", 1.0);
1918 EXPECT_UNRELATED_FIELD_FAILURE(Int, "sI", "I", 1);
1919 EXPECT_UNRELATED_FIELD_FAILURE(Long, "sJ", "J", 1);
1920 EXPECT_UNRELATED_FIELD_FAILURE(Short, "sS", "S", 1);
1921 EXPECT_UNRELATED_FIELD_FAILURE(Object, "sObject", "Ljava/lang/Object;", c);
1922 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001923}
1924
Alex Lighte4033fa2017-12-13 10:32:59 -08001925#define TEST_OBJECT_FIELD_FOR_CLASS(cname) \
1926 do { \
1927 Thread::Current()->TransitionFromSuspendedToRunnable(); \
1928 LoadDex("AllFields"); \
1929 runtime_->Start(); \
1930 \
1931 jclass c = env_->FindClass(cname); \
1932 ASSERT_NE(c, nullptr); \
1933 jobject o = env_->AllocObject(c); \
1934 ASSERT_NE(o, nullptr); \
1935 \
1936 jstring s1 = env_->NewStringUTF("hello"); \
1937 ASSERT_NE(s1, nullptr); \
1938 jstring s2 = env_->NewStringUTF("world"); \
1939 ASSERT_NE(s2, nullptr); \
1940 \
1941 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;"); \
1942 ASSERT_NE(s_fid, nullptr); \
1943 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;"); \
1944 ASSERT_NE(i_fid, nullptr); \
1945 \
1946 env_->SetStaticObjectField(c, s_fid, s1); \
1947 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid))); \
1948 env_->SetStaticObjectField(c, s_fid, s2); \
1949 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid))); \
1950 \
1951 env_->SetObjectField(o, i_fid, s1); \
1952 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid))); \
1953 env_->SetObjectField(o, i_fid, s2); \
1954 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid))); \
1955 } while (false)
1956
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001957TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
Alex Lighte4033fa2017-12-13 10:32:59 -08001958 TEST_OBJECT_FIELD_FOR_CLASS("AllFields");
1959}
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001960
Alex Lighte4033fa2017-12-13 10:32:59 -08001961TEST_F(JniInternalTest, GetObjectField_SetObjectField_subclass) {
1962 TEST_OBJECT_FIELD_FOR_CLASS("AllFieldsSub");
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001963}
1964
Ian Rogers2d10b202014-05-12 19:15:18 -07001965TEST_F(JniInternalTest, NewLocalRef_nullptr) {
1966 EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001967}
1968
1969TEST_F(JniInternalTest, NewLocalRef) {
1970 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001971 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001972 jobject o = env_->NewLocalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001973 EXPECT_NE(o, nullptr);
1974 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07001975
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001976 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
Elliott Hughes18c07532011-08-18 15:50:51 -07001977}
1978
Ian Rogers2d10b202014-05-12 19:15:18 -07001979TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
1980 env_->DeleteLocalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001981}
1982
1983TEST_F(JniInternalTest, DeleteLocalRef) {
Andreas Gampe369810a2015-01-14 19:53:31 -08001984 // This tests leads to warnings and errors in the log.
1985 ScopedLogSeverity sls(LogSeverity::FATAL);
1986
Elliott Hughes18c07532011-08-18 15:50:51 -07001987 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001988 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001989 env_->DeleteLocalRef(s);
1990
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001991 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001992 {
Ian Rogers68d8b422014-07-17 11:09:10 -07001993 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1994 {
1995 CheckJniAbortCatcher check_jni_abort_catcher;
1996 env_->DeleteLocalRef(s);
1997 }
Elliott Hughesb264f082012-04-06 17:10:10 -07001998 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07001999 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
Elliott Hughesb264f082012-04-06 17:10:10 -07002000 env_->DeleteLocalRef(s);
Ian Rogersc0542af2014-09-03 16:16:56 -07002001 std::string expected(StringPrintf("use of deleted local reference %p", s));
Elliott Hughesa9137c62013-01-09 10:55:21 -08002002 check_jni_abort_catcher.Check(expected.c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07002003 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughesb264f082012-04-06 17:10:10 -07002004 }
Elliott Hughes18c07532011-08-18 15:50:51 -07002005
2006 s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002007 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002008 jobject o = env_->NewLocalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002009 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002010
2011 env_->DeleteLocalRef(s);
2012 env_->DeleteLocalRef(o);
2013}
2014
Elliott Hughesaa836f72013-08-20 16:57:23 -07002015TEST_F(JniInternalTest, PushLocalFrame_10395422) {
2016 // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
2017 // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
2018 // Android historically treated it, and it's how the RI treats it. It's also the more useful
2019 // interpretation!
2020 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
Ian Rogers2d10b202014-05-12 19:15:18 -07002021 env_->PopLocalFrame(nullptr);
Elliott Hughesaa836f72013-08-20 16:57:23 -07002022
Andreas Gampe369810a2015-01-14 19:53:31 -08002023 // The following two tests will print errors to the log.
2024 ScopedLogSeverity sls(LogSeverity::FATAL);
2025
Elliott Hughesaa836f72013-08-20 16:57:23 -07002026 // Negative capacities are not allowed.
2027 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
Elliott Hughesaa836f72013-08-20 16:57:23 -07002028}
2029
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002030TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
Andreas Gampe369810a2015-01-14 19:53:31 -08002031 // This tests leads to errors in the log.
2032 ScopedLogSeverity sls(LogSeverity::FATAL);
2033
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002034 jobject original = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002035 ASSERT_NE(original, nullptr);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002036
2037 jobject outer;
2038 jobject inner1, inner2;
Ian Rogers00f7d0e2012-07-19 15:28:27 -07002039 ScopedObjectAccess soa(env_);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002040 {
Elliott Hughesaa836f72013-08-20 16:57:23 -07002041 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002042 outer = env_->NewLocalRef(original);
2043
2044 {
Elliott Hughesaa836f72013-08-20 16:57:23 -07002045 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002046 inner1 = env_->NewLocalRef(outer);
2047 inner2 = env_->NewStringUTF("survivor");
Ian Rogersc0542af2014-09-03 16:16:56 -07002048 EXPECT_NE(env_->PopLocalFrame(inner2), nullptr);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002049 }
2050
2051 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
2052 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
Ian Rogersc0542af2014-09-03 16:16:56 -07002053 {
2054 CheckJniAbortCatcher check_jni_abort_catcher;
2055 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
2056 check_jni_abort_catcher.Check("use of deleted local reference");
2057 }
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002058
2059 // Our local reference for the survivor is invalid because the survivor
2060 // gets a new local reference...
Ian Rogersc0542af2014-09-03 16:16:56 -07002061 {
2062 CheckJniAbortCatcher check_jni_abort_catcher;
2063 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
2064 check_jni_abort_catcher.Check("use of deleted local reference");
2065 }
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002066
Ian Rogersc0542af2014-09-03 16:16:56 -07002067 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002068 }
2069 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
Ian Rogersc0542af2014-09-03 16:16:56 -07002070 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002071 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
Ian Rogersc0542af2014-09-03 16:16:56 -07002072 check_jni_abort_catcher.Check("use of deleted local reference");
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002073 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
Ian Rogersc0542af2014-09-03 16:16:56 -07002074 check_jni_abort_catcher.Check("use of deleted local reference");
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002075 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
Ian Rogersc0542af2014-09-03 16:16:56 -07002076 check_jni_abort_catcher.Check("use of deleted local reference");
Elliott Hughes2ced6a52011-10-16 18:44:48 -07002077}
2078
Andreas Gampe0ece10d2017-05-31 20:09:28 -07002079TEST_F(JniInternalTest, PushLocalFrame_LimitAndOverflow) {
2080 // Try a very large value that should fail.
2081 ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max()));
Andreas Gampe88831082017-05-31 19:46:03 -07002082 ASSERT_TRUE(env_->ExceptionCheck());
2083 env_->ExceptionClear();
Andreas Gampe0ece10d2017-05-31 20:09:28 -07002084
2085 // On 32-bit, also check for some overflow conditions.
2086#ifndef __LP64__
2087 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(10));
2088 ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max() - 10));
2089 ASSERT_TRUE(env_->ExceptionCheck());
2090 env_->ExceptionClear();
2091 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
2092#endif
2093}
2094
Andreas Gampe88831082017-05-31 19:46:03 -07002095TEST_F(JniInternalTest, PushLocalFrame_b62223672) {
2096 // The 512 entry limit has been lifted, try a larger value.
2097 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(1024));
2098 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
2099}
2100
Ian Rogers2d10b202014-05-12 19:15:18 -07002101TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
2102 EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002103}
2104
2105TEST_F(JniInternalTest, NewGlobalRef) {
2106 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002107 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002108 jobject o = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002109 EXPECT_NE(o, nullptr);
2110 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07002111
Ian Rogers2d10b202014-05-12 19:15:18 -07002112 EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
Elliott Hughes18c07532011-08-18 15:50:51 -07002113}
2114
Ian Rogers2d10b202014-05-12 19:15:18 -07002115TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
2116 env_->DeleteGlobalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002117}
2118
2119TEST_F(JniInternalTest, DeleteGlobalRef) {
Andreas Gampe369810a2015-01-14 19:53:31 -08002120 // This tests leads to warnings and errors in the log.
2121 ScopedLogSeverity sls(LogSeverity::FATAL);
2122
Elliott Hughes18c07532011-08-18 15:50:51 -07002123 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002124 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002125
2126 jobject o = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002127 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002128 env_->DeleteGlobalRef(o);
2129
Elliott Hughes3f6635a2012-06-19 13:37:49 -07002130 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07002131 {
Ian Rogers68d8b422014-07-17 11:09:10 -07002132 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2133 {
2134 CheckJniAbortCatcher check_jni_abort_catcher;
2135 env_->DeleteGlobalRef(o);
2136 }
Elliott Hughesb264f082012-04-06 17:10:10 -07002137 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07002138 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
Elliott Hughesb264f082012-04-06 17:10:10 -07002139 env_->DeleteGlobalRef(o);
Ian Rogersc0542af2014-09-03 16:16:56 -07002140 std::string expected(StringPrintf("use of deleted global reference %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08002141 check_jni_abort_catcher.Check(expected.c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07002142 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughesb264f082012-04-06 17:10:10 -07002143 }
Elliott Hughes18c07532011-08-18 15:50:51 -07002144
2145 jobject o1 = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002146 ASSERT_NE(o1, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002147 jobject o2 = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002148 ASSERT_NE(o2, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002149
2150 env_->DeleteGlobalRef(o1);
2151 env_->DeleteGlobalRef(o2);
2152}
2153
Ian Rogers2d10b202014-05-12 19:15:18 -07002154TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
2155 EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002156}
2157
2158TEST_F(JniInternalTest, NewWeakGlobalRef) {
2159 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002160 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002161 jobject o = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002162 EXPECT_NE(o, nullptr);
2163 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07002164
Ian Rogers2d10b202014-05-12 19:15:18 -07002165 EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
Elliott Hughes18c07532011-08-18 15:50:51 -07002166}
2167
Ian Rogers2d10b202014-05-12 19:15:18 -07002168TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
2169 env_->DeleteWeakGlobalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002170}
2171
2172TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
Andreas Gampe369810a2015-01-14 19:53:31 -08002173 // This tests leads to warnings and errors in the log.
2174 ScopedLogSeverity sls(LogSeverity::FATAL);
2175
Elliott Hughes18c07532011-08-18 15:50:51 -07002176 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07002177 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002178
2179 jobject o = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002180 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002181 env_->DeleteWeakGlobalRef(o);
2182
Elliott Hughes3f6635a2012-06-19 13:37:49 -07002183 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07002184 {
Ian Rogers68d8b422014-07-17 11:09:10 -07002185 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2186 {
2187 CheckJniAbortCatcher check_jni_abort_catcher;
2188 env_->DeleteWeakGlobalRef(o);
2189 }
Elliott Hughesb264f082012-04-06 17:10:10 -07002190 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers68d8b422014-07-17 11:09:10 -07002191 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
Elliott Hughesb264f082012-04-06 17:10:10 -07002192 env_->DeleteWeakGlobalRef(o);
Ian Rogersc0542af2014-09-03 16:16:56 -07002193 std::string expected(StringPrintf("use of deleted weak global reference %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08002194 check_jni_abort_catcher.Check(expected.c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07002195 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughesb264f082012-04-06 17:10:10 -07002196 }
Elliott Hughes18c07532011-08-18 15:50:51 -07002197
2198 jobject o1 = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002199 ASSERT_NE(o1, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002200 jobject o2 = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07002201 ASSERT_NE(o2, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07002202
2203 env_->DeleteWeakGlobalRef(o1);
2204 env_->DeleteWeakGlobalRef(o2);
2205}
2206
Alexei Zavjalov3a1444c2014-06-25 16:04:55 +07002207TEST_F(JniInternalTest, ExceptionDescribe) {
2208 // This checks how ExceptionDescribe handles call without exception.
2209 env_->ExceptionClear();
2210 env_->ExceptionDescribe();
2211}
2212
Elliott Hughes37f7a402011-08-22 18:56:01 -07002213TEST_F(JniInternalTest, Throw) {
Elliott Hughes37f7a402011-08-22 18:56:01 -07002214 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
Ian Rogers2d10b202014-05-12 19:15:18 -07002215 ASSERT_TRUE(exception_class != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07002216 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
Ian Rogers2d10b202014-05-12 19:15:18 -07002217 ASSERT_TRUE(exception != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07002218
2219 EXPECT_EQ(JNI_OK, env_->Throw(exception));
2220 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughesa2501992011-08-26 19:39:54 -07002221 jthrowable thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07002222 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07002223 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
Ian Rogers68d8b422014-07-17 11:09:10 -07002224
2225 // Bad argument.
2226 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2227 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
2228 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2229 CheckJniAbortCatcher check_jni_abort_catcher;
2230 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
2231 check_jni_abort_catcher.Check("Throw received NULL jthrowable");
2232 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes37f7a402011-08-22 18:56:01 -07002233}
2234
2235TEST_F(JniInternalTest, ThrowNew) {
Elliott Hughes37f7a402011-08-22 18:56:01 -07002236 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
Ian Rogers2d10b202014-05-12 19:15:18 -07002237 ASSERT_TRUE(exception_class != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07002238
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07002239 jthrowable thrown_exception;
2240
Elliott Hughes37f7a402011-08-22 18:56:01 -07002241 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
2242 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07002243 thrown_exception = env_->ExceptionOccurred();
2244 env_->ExceptionClear();
2245 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
2246
Ian Rogers2d10b202014-05-12 19:15:18 -07002247 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07002248 EXPECT_TRUE(env_->ExceptionCheck());
2249 thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07002250 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07002251 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
Ian Rogers68d8b422014-07-17 11:09:10 -07002252
2253 // Bad argument.
2254 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2255 CheckJniAbortCatcher check_jni_abort_catcher;
2256 EXPECT_EQ(JNI_ERR, env_->ThrowNew(nullptr, nullptr));
2257 check_jni_abort_catcher.Check("c == null");
2258 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2259 EXPECT_EQ(JNI_ERR, env_->ThrowNew(nullptr, nullptr));
2260 check_jni_abort_catcher.Check("ThrowNew received NULL jclass");
2261 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
Elliott Hughes37f7a402011-08-22 18:56:01 -07002262}
2263
Ian Rogers1d99e452014-01-02 17:36:41 -08002264TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
2265 // Start runtime.
2266 Thread* self = Thread::Current();
2267 self->TransitionFromSuspendedToRunnable();
2268 MakeExecutable(nullptr, "java.lang.Class");
2269 MakeExecutable(nullptr, "java.lang.Object");
2270 MakeExecutable(nullptr, "java.nio.DirectByteBuffer");
Yi Kong1fdb6962015-11-19 13:58:04 +00002271 MakeExecutable(nullptr, "java.nio.Bits");
Ian Rogers1d99e452014-01-02 17:36:41 -08002272 MakeExecutable(nullptr, "java.nio.MappedByteBuffer");
2273 MakeExecutable(nullptr, "java.nio.ByteBuffer");
2274 MakeExecutable(nullptr, "java.nio.Buffer");
2275 // TODO: we only load a dex file here as starting the runtime relies upon it.
2276 const char* class_name = "StaticLeafMethods";
2277 LoadDex(class_name);
2278 bool started = runtime_->Start();
2279 ASSERT_TRUE(started);
2280
Elliott Hughesb465ab02011-08-24 11:21:21 -07002281 jclass buffer_class = env_->FindClass("java/nio/Buffer");
Ian Rogers2d10b202014-05-12 19:15:18 -07002282 ASSERT_NE(buffer_class, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07002283
2284 char bytes[1024];
2285 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
Ian Rogers2d10b202014-05-12 19:15:18 -07002286 ASSERT_NE(buffer, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07002287 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
Ian Rogers2d10b202014-05-12 19:15:18 -07002288 ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
Ian Rogers1ee99352014-05-14 14:38:16 -07002289 ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
Brian Carlstrom45d26c82014-06-24 23:36:28 -07002290
2291 {
2292 CheckJniAbortCatcher check_jni_abort_catcher;
Brian Carlstrom85a93362014-06-25 09:30:52 -07002293 env_->NewDirectByteBuffer(bytes, static_cast<jlong>(INT_MAX) + 1);
Brian Carlstrom45d26c82014-06-24 23:36:28 -07002294 check_jni_abort_catcher.Check("in call to NewDirectByteBuffer");
2295 }
Elliott Hughesb465ab02011-08-24 11:21:21 -07002296}
2297
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002298TEST_F(JniInternalTest, MonitorEnterExit) {
Andreas Gampe369810a2015-01-14 19:53:31 -08002299 // This will print some error messages. Suppress.
2300 ScopedLogSeverity sls(LogSeverity::FATAL);
2301
Ian Rogers2d10b202014-05-12 19:15:18 -07002302 // Create an object to torture.
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002303 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -07002304 ASSERT_NE(object_class, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002305 jobject object = env_->AllocObject(object_class);
Ian Rogers2d10b202014-05-12 19:15:18 -07002306 ASSERT_NE(object, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002307
2308 // Expected class of exceptions
2309 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
Ian Rogers2d10b202014-05-12 19:15:18 -07002310 ASSERT_NE(imse_class, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002311
2312 jthrowable thrown_exception;
2313
2314 // Unlock of unowned monitor
2315 env_->MonitorExit(object);
2316 EXPECT_TRUE(env_->ExceptionCheck());
2317 thrown_exception = env_->ExceptionOccurred();
2318 env_->ExceptionClear();
2319 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
2320
2321 // Lock of unowned monitor
2322 env_->MonitorEnter(object);
2323 EXPECT_FALSE(env_->ExceptionCheck());
2324 // Regular unlock
2325 env_->MonitorExit(object);
2326 EXPECT_FALSE(env_->ExceptionCheck());
2327
2328 // Recursively lock a lot
2329 size_t max_recursive_lock = 1024;
2330 for (size_t i = 0; i < max_recursive_lock; i++) {
2331 env_->MonitorEnter(object);
2332 EXPECT_FALSE(env_->ExceptionCheck());
2333 }
2334 // Recursively unlock a lot
2335 for (size_t i = 0; i < max_recursive_lock; i++) {
2336 env_->MonitorExit(object);
2337 EXPECT_FALSE(env_->ExceptionCheck());
2338 }
2339
2340 // Unlock of unowned monitor
2341 env_->MonitorExit(object);
2342 EXPECT_TRUE(env_->ExceptionCheck());
2343 thrown_exception = env_->ExceptionOccurred();
2344 env_->ExceptionClear();
2345 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
Elliott Hughesa92853e2012-02-07 16:09:27 -08002346
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002347 // It's an error to call MonitorEnter or MonitorExit on null.
Elliott Hughesb264f082012-04-06 17:10:10 -07002348 {
2349 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers2d10b202014-05-12 19:15:18 -07002350 env_->MonitorEnter(nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07002351 check_jni_abort_catcher.Check("in call to MonitorEnter");
Ian Rogers2d10b202014-05-12 19:15:18 -07002352 env_->MonitorExit(nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07002353 check_jni_abort_catcher.Check("in call to MonitorExit");
2354 }
Ian Rogers6d0b13e2012-02-07 09:25:29 -08002355}
2356
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002357void Java_MyClassNatives_foo_exit(JNIEnv* env, jobject thisObj) {
2358 // Release the monitor on self. This should trigger an abort.
2359 env->MonitorExit(thisObj);
2360}
2361
2362TEST_F(JniInternalTest, MonitorExitLockedInDifferentCall) {
2363 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo_exit));
2364 ASSERT_NE(jobj_, nullptr);
2365
2366 env_->MonitorEnter(jobj_);
2367 EXPECT_FALSE(env_->ExceptionCheck());
2368
2369 CheckJniAbortCatcher check_jni_abort_catcher;
2370 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
2371 check_jni_abort_catcher.Check("Unlocking monitor that wasn't locked here");
2372}
2373
2374void Java_MyClassNatives_foo_enter_no_exit(JNIEnv* env, jobject thisObj) {
2375 // Acquire but don't release the monitor on self. This should trigger an abort on return.
2376 env->MonitorEnter(thisObj);
2377}
2378
2379TEST_F(JniInternalTest, MonitorExitNotAllUnlocked) {
2380 SetUpForTest(false,
2381 "foo",
2382 "()V",
2383 reinterpret_cast<void*>(&Java_MyClassNatives_foo_enter_no_exit));
2384 ASSERT_NE(jobj_, nullptr);
2385
2386 CheckJniAbortCatcher check_jni_abort_catcher;
2387 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
2388 check_jni_abort_catcher.Check("Still holding a locked object on JNI end");
2389}
2390
Andreas Gampeb8c4f032015-12-03 10:56:18 -08002391static bool IsLocked(JNIEnv* env, jobject jobj) {
2392 ScopedObjectAccess soa(env);
Mathieu Chartier0795f232016-09-27 18:43:30 -07002393 LockWord lock_word = soa.Decode<mirror::Object>(jobj)->GetLockWord(true);
Andreas Gampeb8c4f032015-12-03 10:56:18 -08002394 switch (lock_word.GetState()) {
2395 case LockWord::kHashCode:
2396 case LockWord::kUnlocked:
2397 return false;
2398 case LockWord::kThinLocked:
2399 return true;
2400 case LockWord::kFatLocked:
2401 return lock_word.FatLockMonitor()->IsLocked();
2402 default: {
2403 LOG(FATAL) << "Invalid monitor state " << lock_word.GetState();
2404 UNREACHABLE();
2405 }
2406 }
2407}
2408
2409TEST_F(JniInternalTest, DetachThreadUnlockJNIMonitors) {
2410 // We need to lock an object, detach, reattach, and check the locks.
2411 //
2412 // As re-attaching will create a different thread, we need to use a global
2413 // ref to keep the object around.
2414
2415 // Create an object to torture.
2416 jobject global_ref;
2417 {
2418 jclass object_class = env_->FindClass("java/lang/Object");
2419 ASSERT_NE(object_class, nullptr);
2420 jobject object = env_->AllocObject(object_class);
2421 ASSERT_NE(object, nullptr);
2422 global_ref = env_->NewGlobalRef(object);
2423 }
2424
2425 // Lock it.
2426 env_->MonitorEnter(global_ref);
2427 ASSERT_TRUE(IsLocked(env_, global_ref));
2428
2429 // Detach and re-attach.
2430 jint detach_result = vm_->DetachCurrentThread();
2431 ASSERT_EQ(detach_result, JNI_OK);
2432 jint attach_result = vm_->AttachCurrentThread(&env_, nullptr);
2433 ASSERT_EQ(attach_result, JNI_OK);
2434
2435 // Look at the global ref, check whether it's still locked.
2436 ASSERT_FALSE(IsLocked(env_, global_ref));
2437
2438 // Delete the global ref.
2439 env_->DeleteGlobalRef(global_ref);
2440}
2441
Andreas Gampeda9b7632015-12-09 15:14:04 -08002442// Test the offset computation of IndirectReferenceTable offsets. b/26071368.
2443TEST_F(JniInternalTest, IndirectReferenceTableOffsets) {
2444 // The segment_state_ field is private, and we want to avoid friend declaration. So we'll check
2445 // by modifying memory.
2446 // The parameters don't really matter here.
Richard Uhlerda0a69e2016-10-11 15:06:38 +01002447 std::string error_msg;
Andreas Gampe9d7ef622016-10-24 19:35:19 -07002448 IndirectReferenceTable irt(5,
2449 IndirectRefKind::kGlobal,
2450 IndirectReferenceTable::ResizableCapacity::kNo,
2451 &error_msg);
Richard Uhlerda0a69e2016-10-11 15:06:38 +01002452 ASSERT_TRUE(irt.IsValid()) << error_msg;
Andreas Gampee03662b2016-10-13 17:12:56 -07002453 IRTSegmentState old_state = irt.GetSegmentState();
Andreas Gampeda9b7632015-12-09 15:14:04 -08002454
2455 // Write some new state directly. We invert parts of old_state to ensure a new value.
Andreas Gampee03662b2016-10-13 17:12:56 -07002456 IRTSegmentState new_state;
2457 new_state.top_index = old_state.top_index ^ 0x07705005;
2458 ASSERT_NE(old_state.top_index, new_state.top_index);
Andreas Gampeda9b7632015-12-09 15:14:04 -08002459
2460 uint8_t* base = reinterpret_cast<uint8_t*>(&irt);
2461 int32_t segment_state_offset =
2462 IndirectReferenceTable::SegmentStateOffset(sizeof(void*)).Int32Value();
Andreas Gampee03662b2016-10-13 17:12:56 -07002463 *reinterpret_cast<IRTSegmentState*>(base + segment_state_offset) = new_state;
Andreas Gampeda9b7632015-12-09 15:14:04 -08002464
2465 // Read and compare.
Andreas Gampee03662b2016-10-13 17:12:56 -07002466 EXPECT_EQ(new_state.top_index, irt.GetSegmentState().top_index);
Andreas Gampeda9b7632015-12-09 15:14:04 -08002467}
2468
2469// Test the offset computation of JNIEnvExt offsets. b/26071368.
2470TEST_F(JniInternalTest, JNIEnvExtOffsets) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002471 EXPECT_EQ(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie_),
Vladimir Marko46817b82016-03-29 12:21:58 +01002472 JNIEnvExt::LocalRefCookieOffset(sizeof(void*)).Uint32Value());
Andreas Gampeda9b7632015-12-09 15:14:04 -08002473
Ian Rogers55256cb2017-12-21 17:07:11 -08002474 EXPECT_EQ(OFFSETOF_MEMBER(JNIEnvExt, self_), JNIEnvExt::SelfOffset(sizeof(void*)).Uint32Value());
Andreas Gampeda9b7632015-12-09 15:14:04 -08002475
2476 // segment_state_ is private in the IndirectReferenceTable. So this test isn't as good as we'd
2477 // hope it to be.
Vladimir Marko46817b82016-03-29 12:21:58 +01002478 uint32_t segment_state_now =
Ian Rogers55256cb2017-12-21 17:07:11 -08002479 OFFSETOF_MEMBER(JNIEnvExt, locals_) +
Vladimir Marko46817b82016-03-29 12:21:58 +01002480 IndirectReferenceTable::SegmentStateOffset(sizeof(void*)).Uint32Value();
2481 uint32_t segment_state_computed = JNIEnvExt::SegmentStateOffset(sizeof(void*)).Uint32Value();
Andreas Gampeda9b7632015-12-09 15:14:04 -08002482 EXPECT_EQ(segment_state_now, segment_state_computed);
2483}
2484
Andreas Gampec8089542017-01-16 12:41:12 -08002485static size_t gGlobalRefCount = 0;
2486static const JNINativeInterface* gOriginalEnv = nullptr;
2487
2488static jobject CountNewGlobalRef(JNIEnv* env, jobject o) {
2489 ++gGlobalRefCount;
2490 return gOriginalEnv->NewGlobalRef(env, o);
2491}
2492
2493// Test the table override.
2494TEST_F(JniInternalTest, JNIEnvExtTableOverride) {
2495 JNINativeInterface env_override;
2496 memcpy(&env_override, env_->functions, sizeof(JNINativeInterface));
2497
2498 gOriginalEnv = env_->functions;
2499 env_override.NewGlobalRef = CountNewGlobalRef;
2500 gGlobalRefCount = 0;
2501
2502 jclass local = env_->FindClass("java/lang/Object");
2503 ASSERT_TRUE(local != nullptr);
2504
2505 // Set the table, add a global ref, see whether the counter increases.
2506 JNIEnvExt::SetTableOverride(&env_override);
2507
2508 jobject global = env_->NewGlobalRef(local);
2509 EXPECT_EQ(1u, gGlobalRefCount);
2510 env_->DeleteGlobalRef(global);
2511
2512 // Reset
2513 JNIEnvExt::SetTableOverride(nullptr);
2514
2515 jobject global2 = env_->NewGlobalRef(local);
2516 EXPECT_EQ(1u, gGlobalRefCount);
2517 env_->DeleteGlobalRef(global2);
2518}
2519
Andreas Gampe69944c92018-04-17 11:08:23 -07002520TEST_F(JniInternalTest, NonAttachedThread) {
2521 // This tests leads to warnings and errors in the log.
2522 ScopedLogSeverity sls(LogSeverity::FATAL);
2523 CheckJniAbortCatcher check_jni_abort_catcher;
2524
2525 auto callee = [](void* env_ptr) -> void* {
2526 JNIEnv* env = reinterpret_cast<JNIEnv*>(env_ptr);
2527 env->NewStringUTF("test");
2528 return nullptr;
2529 };
2530
2531 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2532 vm_->SetCheckJniEnabled(true);
2533 {
2534 pthread_t pthread;
2535 int pthread_create_result = pthread_create(&pthread,
2536 /* pthread_attr */ nullptr,
2537 callee,
2538 reinterpret_cast<void*>(env_));
2539 CHECK_EQ(pthread_create_result, 0);
2540 int pthread_join_result = pthread_join(pthread, /* thread_return */ nullptr);
2541 CHECK_EQ(pthread_join_result, 0);
2542 }
2543 vm_->SetCheckJniEnabled(old_check_jni);
2544
2545 check_jni_abort_catcher.Check("is making JNI calls without being attached");
2546}
2547
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07002548} // namespace art