jni_internal_test.cc revision d4c3c62cc68296fbaf35e7b37108c2fde2278a3b
1/*
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 */
16
17#include "jni_internal.h"
18
19#include "common_compiler_test.h"
20#include "mirror/art_method-inl.h"
21#include "mirror/string-inl.h"
22#include "ScopedLocalRef.h"
23
24namespace art {
25
26// TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used.
27class JniInternalTest : public CommonCompilerTest {
28 protected:
29  virtual void SetUp() {
30    CommonCompilerTest::SetUp();
31
32    vm_ = Runtime::Current()->GetJavaVM();
33
34    // Turn on -verbose:jni for the JNI tests.
35    // gLogVerbosity.jni = true;
36
37    vm_->AttachCurrentThread(&env_, nullptr);
38
39    ScopedLocalRef<jclass> aioobe(env_,
40                                  env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
41    CHECK(aioobe.get() != nullptr);
42    aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
43
44    ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
45    CHECK(ase.get() != nullptr);
46    ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
47
48    ScopedLocalRef<jclass> sioobe(env_,
49                                  env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
50    CHECK(sioobe.get() != nullptr);
51    sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
52  }
53
54  void ExpectException(jclass exception_class) {
55    EXPECT_TRUE(env_->ExceptionCheck());
56    jthrowable exception = env_->ExceptionOccurred();
57    EXPECT_NE(nullptr, exception);
58    env_->ExceptionClear();
59    EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
60  }
61
62  void ExpectClassFound(const char* name) {
63    EXPECT_NE(env_->FindClass(name), nullptr) << name;
64    EXPECT_FALSE(env_->ExceptionCheck()) << name;
65  }
66
67  void ExpectClassNotFound(const char* name) {
68    EXPECT_EQ(env_->FindClass(name), nullptr) << name;
69    EXPECT_TRUE(env_->ExceptionCheck()) << name;
70    env_->ExceptionClear();
71  }
72
73  void CleanUpJniEnv() {
74    if (aioobe_ != nullptr) {
75      env_->DeleteGlobalRef(aioobe_);
76      aioobe_ = nullptr;
77    }
78    if (ase_ != nullptr) {
79      env_->DeleteGlobalRef(ase_);
80      ase_ = nullptr;
81    }
82    if (sioobe_ != nullptr) {
83      env_->DeleteGlobalRef(sioobe_);
84      sioobe_ = nullptr;
85    }
86  }
87
88  virtual void TearDown() OVERRIDE {
89    CleanUpJniEnv();
90    CommonCompilerTest::TearDown();
91  }
92
93  jclass GetPrimitiveClass(char descriptor) {
94    ScopedObjectAccess soa(env_);
95    mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
96    CHECK(c != nullptr);
97    return soa.AddLocalReference<jclass>(c);
98  }
99
100  JavaVMExt* vm_;
101  JNIEnv* env_;
102  jclass aioobe_;
103  jclass ase_;
104  jclass sioobe_;
105};
106
107TEST_F(JniInternalTest, AllocObject) {
108  jclass c = env_->FindClass("java/lang/String");
109  ASSERT_NE(c, nullptr);
110  jobject o = env_->AllocObject(c);
111  ASSERT_NE(o, nullptr);
112
113  // We have an instance of the class we asked for...
114  ASSERT_TRUE(env_->IsInstanceOf(o, c));
115  // ...whose fields haven't been initialized because
116  // we didn't call a constructor.
117  ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
118  ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
119  ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr);
120}
121
122TEST_F(JniInternalTest, GetVersion) {
123  ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
124}
125
126TEST_F(JniInternalTest, FindClass) {
127  // Reference types...
128  ExpectClassFound("java/lang/String");
129  // ...for arrays too, where you must include "L;".
130  ExpectClassFound("[Ljava/lang/String;");
131  // Primitive arrays are okay too, if the primitive type is valid.
132  ExpectClassFound("[C");
133
134  {
135    CheckJniAbortCatcher check_jni_abort_catcher;
136    env_->FindClass(nullptr);
137    check_jni_abort_catcher.Check("name == null");
138
139    // We support . as well as / for compatibility, if -Xcheck:jni is off.
140    ExpectClassFound("java.lang.String");
141    check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
142    ExpectClassNotFound("Ljava.lang.String;");
143    check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
144    ExpectClassFound("[Ljava.lang.String;");
145    check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
146    ExpectClassNotFound("[java.lang.String");
147    check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
148
149    // You can't include the "L;" in a JNI class descriptor.
150    ExpectClassNotFound("Ljava/lang/String;");
151    check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
152
153    // But you must include it for an array of any reference type.
154    ExpectClassNotFound("[java/lang/String");
155    check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
156
157    ExpectClassNotFound("[K");
158    check_jni_abort_catcher.Check("illegal class name '[K'");
159
160    // Void arrays aren't allowed.
161    ExpectClassNotFound("[V");
162    check_jni_abort_catcher.Check("illegal class name '[V'");
163  }
164
165  // But primitive types aren't allowed...
166  ExpectClassNotFound("C");
167  ExpectClassNotFound("V");
168  ExpectClassNotFound("K");
169}
170
171TEST_F(JniInternalTest, GetFieldID) {
172  jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
173  ASSERT_NE(jlnsfe, nullptr);
174  jclass c = env_->FindClass("java/lang/String");
175  ASSERT_NE(c, nullptr);
176
177  // Wrong type.
178  jfieldID fid = env_->GetFieldID(c, "count", "J");
179  EXPECT_EQ(nullptr, fid);
180  ExpectException(jlnsfe);
181
182  // Wrong type where type doesn't exist.
183  fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
184  EXPECT_EQ(nullptr, fid);
185  ExpectException(jlnsfe);
186
187  // Wrong name.
188  fid = env_->GetFieldID(c, "Count", "I");
189  EXPECT_EQ(nullptr, fid);
190  ExpectException(jlnsfe);
191
192  // Good declared field lookup.
193  fid = env_->GetFieldID(c, "count", "I");
194  EXPECT_NE(nullptr, fid);
195  EXPECT_FALSE(env_->ExceptionCheck());
196
197  // Good superclass field lookup.
198  c = env_->FindClass("java/lang/StringBuilder");
199  fid = env_->GetFieldID(c, "count", "I");
200  EXPECT_NE(nullptr, fid);
201  EXPECT_NE(fid, nullptr);
202  EXPECT_FALSE(env_->ExceptionCheck());
203
204  // Not instance.
205  fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
206  EXPECT_EQ(nullptr, fid);
207  ExpectException(jlnsfe);
208
209  // Bad arguments.
210  CheckJniAbortCatcher check_jni_abort_catcher;
211  fid = env_->GetFieldID(nullptr, "count", "I");
212  EXPECT_EQ(nullptr, fid);
213  check_jni_abort_catcher.Check("java_class == null");
214  fid = env_->GetFieldID(c, nullptr, "I");
215  EXPECT_EQ(nullptr, fid);
216  check_jni_abort_catcher.Check("name == null");
217  fid = env_->GetFieldID(c, "count", nullptr);
218  EXPECT_EQ(nullptr, fid);
219  check_jni_abort_catcher.Check("sig == null");
220}
221
222TEST_F(JniInternalTest, GetStaticFieldID) {
223  jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
224  ASSERT_NE(jlnsfe, nullptr);
225  jclass c = env_->FindClass("java/lang/String");
226  ASSERT_NE(c, nullptr);
227
228  // Wrong type.
229  jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
230  EXPECT_EQ(nullptr, fid);
231  ExpectException(jlnsfe);
232
233  // Wrong type where type doesn't exist.
234  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
235  EXPECT_EQ(nullptr, fid);
236  ExpectException(jlnsfe);
237
238  // Wrong name.
239  fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
240  EXPECT_EQ(nullptr, fid);
241  ExpectException(jlnsfe);
242
243  // Good declared field lookup.
244  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
245  EXPECT_NE(nullptr, fid);
246  EXPECT_NE(fid, nullptr);
247  EXPECT_FALSE(env_->ExceptionCheck());
248
249  // Not static.
250  fid = env_->GetStaticFieldID(c, "count", "I");
251  EXPECT_EQ(nullptr, fid);
252  ExpectException(jlnsfe);
253
254  // Bad arguments.
255  CheckJniAbortCatcher check_jni_abort_catcher;
256  fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
257  EXPECT_EQ(nullptr, fid);
258  check_jni_abort_catcher.Check("java_class == null");
259  fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
260  EXPECT_EQ(nullptr, fid);
261  check_jni_abort_catcher.Check("name == null");
262  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
263  EXPECT_EQ(nullptr, fid);
264  check_jni_abort_catcher.Check("sig == null");
265}
266
267TEST_F(JniInternalTest, GetMethodID) {
268  jclass jlobject = env_->FindClass("java/lang/Object");
269  jclass jlstring = env_->FindClass("java/lang/String");
270  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
271  jclass jncrbc = env_->FindClass("java/nio/channels/ReadableByteChannel");
272
273  // Sanity check that no exceptions are pending.
274  ASSERT_FALSE(env_->ExceptionCheck());
275
276  // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
277  // a pending exception.
278  jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
279  EXPECT_EQ(nullptr, method);
280  ExpectException(jlnsme);
281
282  // Check that java.lang.Object.equals() does exist.
283  method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
284  EXPECT_NE(nullptr, method);
285  EXPECT_FALSE(env_->ExceptionCheck());
286
287  // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
288  // method is static.
289  method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
290  EXPECT_EQ(nullptr, method);
291  ExpectException(jlnsme);
292
293  // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor.
294  method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
295  EXPECT_NE(nullptr, method);
296  EXPECT_FALSE(env_->ExceptionCheck());
297
298  // Check that GetMethodID can find a interface method inherited from another interface.
299  method = env_->GetMethodID(jncrbc, "close", "()V");
300  EXPECT_NE(nullptr, method);
301  EXPECT_FALSE(env_->ExceptionCheck());
302
303  // Bad arguments.
304  CheckJniAbortCatcher check_jni_abort_catcher;
305  method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
306  EXPECT_EQ(nullptr, method);
307  check_jni_abort_catcher.Check("java_class == null");
308  method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
309  EXPECT_EQ(nullptr, method);
310  check_jni_abort_catcher.Check("name == null");
311  method = env_->GetMethodID(jlnsme, "<init>", nullptr);
312  EXPECT_EQ(nullptr, method);
313  check_jni_abort_catcher.Check("sig == null");
314}
315
316TEST_F(JniInternalTest, GetStaticMethodID) {
317  jclass jlobject = env_->FindClass("java/lang/Object");
318  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
319
320  // Sanity check that no exceptions are pending
321  ASSERT_FALSE(env_->ExceptionCheck());
322
323  // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
324  // a pending exception
325  jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
326  EXPECT_EQ(nullptr, method);
327  ExpectException(jlnsme);
328
329  // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
330  // the method is not static
331  method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
332  EXPECT_EQ(nullptr, method);
333  ExpectException(jlnsme);
334
335  // Check that java.lang.String.valueOf(int) does exist
336  jclass jlstring = env_->FindClass("java/lang/String");
337  method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
338  EXPECT_NE(nullptr, method);
339  EXPECT_FALSE(env_->ExceptionCheck());
340
341  // Bad arguments.
342  CheckJniAbortCatcher check_jni_abort_catcher;
343  method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
344  EXPECT_EQ(nullptr, method);
345  check_jni_abort_catcher.Check("java_class == null");
346  method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
347  EXPECT_EQ(nullptr, method);
348  check_jni_abort_catcher.Check("name == null");
349  method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
350  EXPECT_EQ(nullptr, method);
351  check_jni_abort_catcher.Check("sig == null");
352}
353
354TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
355  jclass jlrField = env_->FindClass("java/lang/reflect/Field");
356  jclass c = env_->FindClass("java/lang/String");
357  ASSERT_NE(c, nullptr);
358  jfieldID fid = env_->GetFieldID(c, "count", "I");
359  ASSERT_NE(fid, nullptr);
360  // Turn the fid into a java.lang.reflect.Field...
361  jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
362  ASSERT_NE(c, nullptr);
363  ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
364  // ...and back again.
365  jfieldID fid2 = env_->FromReflectedField(field);
366  ASSERT_NE(fid2, nullptr);
367  // Make sure we can actually use it.
368  jstring s = env_->NewStringUTF("poop");
369  ASSERT_EQ(4, env_->GetIntField(s, fid2));
370
371  // Bad arguments.
372  CheckJniAbortCatcher check_jni_abort_catcher;
373  field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
374  EXPECT_EQ(field, nullptr);
375  check_jni_abort_catcher.Check("fid == null");
376  fid2 = env_->FromReflectedField(nullptr);
377  ASSERT_EQ(fid2, nullptr);
378  check_jni_abort_catcher.Check("jlr_field == null");
379}
380
381TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
382  jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
383  ASSERT_NE(jlrMethod, nullptr);
384  jclass jlrConstructor = env_->FindClass("java/lang/reflect/Constructor");
385  ASSERT_NE(jlrConstructor, nullptr);
386  jclass c = env_->FindClass("java/lang/String");
387  ASSERT_NE(c, nullptr);
388
389  jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
390  ASSERT_NE(mid, nullptr);
391  // Turn the mid into a java.lang.reflect.Constructor...
392  jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
393  ASSERT_NE(method, nullptr);
394  ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor));
395  // ...and back again.
396  jmethodID mid2 = env_->FromReflectedMethod(method);
397  ASSERT_NE(mid2, nullptr);
398  // Make sure we can actually use it.
399  jstring s = reinterpret_cast<jstring>(env_->AllocObject(c));
400  ASSERT_NE(s, nullptr);
401  env_->CallVoidMethod(s, mid2);
402  ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck());
403
404  mid = env_->GetMethodID(c, "length", "()I");
405  ASSERT_NE(mid, nullptr);
406  // Turn the mid into a java.lang.reflect.Method...
407  method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
408  ASSERT_NE(method, nullptr);
409  ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
410  // ...and back again.
411  mid2 = env_->FromReflectedMethod(method);
412  ASSERT_NE(mid2, nullptr);
413  // Make sure we can actually use it.
414  s = env_->NewStringUTF("poop");
415  ASSERT_NE(s, nullptr);
416  ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
417
418  // Bad arguments.
419  CheckJniAbortCatcher check_jni_abort_catcher;
420  method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
421  EXPECT_EQ(method, nullptr);
422  check_jni_abort_catcher.Check("mid == null");
423  mid2 = env_->FromReflectedMethod(method);
424  ASSERT_EQ(mid2, nullptr);
425  check_jni_abort_catcher.Check("jlr_method == null");
426}
427
428static void BogusMethod() {
429  // You can't pass nullptr function pointers to RegisterNatives.
430}
431
432TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
433  jclass jlobject = env_->FindClass("java/lang/Object");
434  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
435  void* native_function = reinterpret_cast<void*>(BogusMethod);
436
437  // Sanity check that no exceptions are pending.
438  ASSERT_FALSE(env_->ExceptionCheck());
439
440  // Check that registering method without name causes a NoSuchMethodError.
441  {
442    JNINativeMethod methods[] = { { nullptr, "()V", native_function } };
443    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
444  }
445  ExpectException(jlnsme);
446
447  // Check that registering method without signature causes a NoSuchMethodError.
448  {
449    JNINativeMethod methods[] = { { "notify", nullptr, native_function } };
450    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
451  }
452  ExpectException(jlnsme);
453
454  // Check that registering method without function causes a NoSuchMethodError.
455  {
456    JNINativeMethod methods[] = { { "notify", "()V", nullptr } };
457    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
458  }
459  ExpectException(jlnsme);
460
461  // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
462  {
463    JNINativeMethod methods[] = { { "foo", "()V", native_function } };
464    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
465  }
466  ExpectException(jlnsme);
467
468  // Check that registering non-native methods causes a NoSuchMethodError.
469  {
470    JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", native_function } };
471    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
472  }
473  ExpectException(jlnsme);
474
475  // Check that registering native methods is successful.
476  {
477    JNINativeMethod methods[] = { { "notify", "()V", native_function } };
478    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
479  }
480  EXPECT_FALSE(env_->ExceptionCheck());
481  EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
482
483  // Check that registering no methods isn't a failure.
484  {
485    JNINativeMethod methods[] = { };
486    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
487  }
488  EXPECT_FALSE(env_->ExceptionCheck());
489  EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
490
491  // Check that registering a -ve number of methods is a failure.
492  CheckJniAbortCatcher check_jni_abort_catcher;
493  for (int i = -10; i < 0; ++i) {
494    JNINativeMethod methods[] = { };
495    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
496    check_jni_abort_catcher.Check("negative method count: ");
497  }
498  EXPECT_FALSE(env_->ExceptionCheck());
499
500  // Passing a class of null is a failure.
501  {
502    JNINativeMethod methods[] = { };
503    EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
504    check_jni_abort_catcher.Check("java_class == null");
505  }
506
507  // Passing methods as null is a failure.
508  EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
509  check_jni_abort_catcher.Check("methods == null");
510
511  // Unregisters null is a failure.
512  EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
513  check_jni_abort_catcher.Check("java_class == null");
514
515  // Unregistering a class with no natives is a warning.
516  EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
517}
518
519#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
520                               get_region_fn, \
521                               set_region_fn, \
522                               get_elements_fn, \
523                               release_elements_fn, \
524                               scalar_type, \
525                               expected_class_descriptor) \
526  jsize size = 4; \
527  \
528  { \
529    CheckJniAbortCatcher jni_abort_catcher; \
530    /* Allocate an negative sized array and check it has the right failure type. */ \
531    EXPECT_EQ(env_->new_fn(-1), nullptr); \
532    jni_abort_catcher.Check("negative array length: -1"); \
533    EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
534    jni_abort_catcher.Check("negative array length: -2147483648"); \
535    /* Pass the array as null. */ \
536    EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
537    jni_abort_catcher.Check("java_array == null"); \
538    env_->get_region_fn(nullptr, 0, 0, nullptr); \
539    jni_abort_catcher.Check("java_array == null"); \
540    env_->set_region_fn(nullptr, 0, 0, nullptr); \
541    jni_abort_catcher.Check("java_array == null"); \
542    env_->get_elements_fn(nullptr, nullptr); \
543    jni_abort_catcher.Check("java_array == null"); \
544    env_->release_elements_fn(nullptr, nullptr, 0); \
545    jni_abort_catcher.Check("java_array == null"); \
546    /* Pass the elements for region as null. */ \
547    scalar_type ## Array a = env_->new_fn(size); \
548    env_->get_region_fn(a, 0, size, nullptr); \
549    jni_abort_catcher.Check("buf == null"); \
550    env_->set_region_fn(a, 0, size, nullptr); \
551    jni_abort_catcher.Check("buf == null"); \
552  } \
553  /* Allocate an array and check it has the right type and length. */ \
554  scalar_type ## Array a = env_->new_fn(size); \
555  EXPECT_NE(a, nullptr); \
556  EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
557  EXPECT_EQ(size, env_->GetArrayLength(a)); \
558  \
559  /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
560  /* AIOOBE for negative start offset. */ \
561  env_->get_region_fn(a, -1, 1, nullptr); \
562  ExpectException(aioobe_); \
563  env_->set_region_fn(a, -1, 1, nullptr); \
564  ExpectException(aioobe_); \
565  \
566  /* AIOOBE for negative length. */ \
567  env_->get_region_fn(a, 0, -1, nullptr); \
568  ExpectException(aioobe_); \
569  env_->set_region_fn(a, 0, -1, nullptr); \
570  ExpectException(aioobe_); \
571  \
572  /* AIOOBE for buffer overrun. */ \
573  env_->get_region_fn(a, size - 1, size, nullptr); \
574  ExpectException(aioobe_); \
575  env_->set_region_fn(a, size - 1, size, nullptr); \
576  ExpectException(aioobe_); \
577  \
578  /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
579  env_->get_region_fn(a, 2, 0, nullptr); \
580  /* Even if the offset is invalid... */ \
581  env_->get_region_fn(a, 123, 0, nullptr); \
582  ExpectException(aioobe_); \
583  \
584  /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
585  env_->set_region_fn(a, 2, 0, nullptr); \
586  /* Even if the offset is invalid... */ \
587  env_->set_region_fn(a, 123, 0, nullptr); \
588  ExpectException(aioobe_); \
589  \
590  /* Prepare a couple of buffers. */ \
591  std::unique_ptr<scalar_type[]> src_buf(new scalar_type[size]); \
592  std::unique_ptr<scalar_type[]> dst_buf(new scalar_type[size]); \
593  for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
594  for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
595  \
596  /* Copy all of src_buf onto the heap. */ \
597  env_->set_region_fn(a, 0, size, &src_buf[0]); \
598  /* Copy back only part. */ \
599  env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
600  EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
601    << "short copy equal"; \
602  /* Copy the missing pieces. */ \
603  env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
604  env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
605  EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
606    << "fixed copy not equal"; \
607  /* Copy back the whole array. */ \
608  env_->get_region_fn(a, 0, size, &dst_buf[0]); \
609  EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
610    << "full copy not equal"; \
611  /* GetPrimitiveArrayCritical */ \
612  void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
613  EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
614    << "GetPrimitiveArrayCritical not equal"; \
615  env_->ReleasePrimitiveArrayCritical(a, v, 0); \
616  /* GetXArrayElements */ \
617  scalar_type* xs = env_->get_elements_fn(a, nullptr); \
618  EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
619    << # get_elements_fn " not equal"; \
620  env_->release_elements_fn(a, xs, 0); \
621
622TEST_F(JniInternalTest, BooleanArrays) {
623  EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
624                         GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
625}
626TEST_F(JniInternalTest, ByteArrays) {
627  EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
628                         GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
629}
630TEST_F(JniInternalTest, CharArrays) {
631  EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
632                         GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
633}
634TEST_F(JniInternalTest, DoubleArrays) {
635  EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
636                         GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
637}
638TEST_F(JniInternalTest, FloatArrays) {
639  EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
640                         GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
641}
642TEST_F(JniInternalTest, IntArrays) {
643  EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
644                         GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
645}
646TEST_F(JniInternalTest, LongArrays) {
647  EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
648                         GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
649}
650TEST_F(JniInternalTest, ShortArrays) {
651  EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
652                         GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
653}
654
655TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
656  CheckJniAbortCatcher jni_abort_catcher;
657  jbooleanArray array = env_->NewBooleanArray(10);
658  jboolean is_copy;
659  EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
660  jni_abort_catcher.Check(
661      "attempt to get byte primitive array elements with an object of type boolean[]");
662  EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
663  jni_abort_catcher.Check(
664      "attempt to get short primitive array elements with an object of type boolean[]");
665  EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
666  jni_abort_catcher.Check(
667      "attempt to get char primitive array elements with an object of type boolean[]");
668  EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
669  jni_abort_catcher.Check(
670      "attempt to get int primitive array elements with an object of type boolean[]");
671  EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
672  jni_abort_catcher.Check(
673      "attempt to get long primitive array elements with an object of type boolean[]");
674  EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
675  jni_abort_catcher.Check(
676      "attempt to get float primitive array elements with an object of type boolean[]");
677  EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
678  jni_abort_catcher.Check(
679      "attempt to get double primitive array elements with an object of type boolean[]");
680  jbyteArray array2 = env_->NewByteArray(10);
681  EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy),
682            nullptr);
683  jni_abort_catcher.Check(
684      "attempt to get boolean primitive array elements with an object of type byte[]");
685  jobject object = env_->NewStringUTF("Test String");
686  EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy),
687            nullptr);
688  jni_abort_catcher.Check(
689      "attempt to get boolean primitive array elements with an object of type java.lang.String");
690}
691
692TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
693  CheckJniAbortCatcher jni_abort_catcher;
694  jbooleanArray array = env_->NewBooleanArray(10);
695  ASSERT_TRUE(array != nullptr);
696  jboolean is_copy;
697  jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
698  ASSERT_TRUE(elements != nullptr);
699  env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
700                                 reinterpret_cast<jbyte*>(elements), 0);
701  jni_abort_catcher.Check(
702      "attempt to release byte primitive array elements with an object of type boolean[]");
703  env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
704                                  reinterpret_cast<jshort*>(elements), 0);
705  jni_abort_catcher.Check(
706      "attempt to release short primitive array elements with an object of type boolean[]");
707  env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
708                                 reinterpret_cast<jchar*>(elements), 0);
709  jni_abort_catcher.Check(
710      "attempt to release char primitive array elements with an object of type boolean[]");
711  env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
712                                reinterpret_cast<jint*>(elements), 0);
713  jni_abort_catcher.Check(
714      "attempt to release int primitive array elements with an object of type boolean[]");
715  env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
716                                 reinterpret_cast<jlong*>(elements), 0);
717  jni_abort_catcher.Check(
718      "attempt to release long primitive array elements with an object of type boolean[]");
719  env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
720                                  reinterpret_cast<jfloat*>(elements), 0);
721  jni_abort_catcher.Check(
722      "attempt to release float primitive array elements with an object of type boolean[]");
723  env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
724                                  reinterpret_cast<jdouble*>(elements), 0);
725  jni_abort_catcher.Check(
726      "attempt to release double primitive array elements with an object of type boolean[]");
727  jbyteArray array2 = env_->NewByteArray(10);
728  env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0);
729  jni_abort_catcher.Check(
730      "attempt to release boolean primitive array elements with an object of type byte[]");
731  jobject object = env_->NewStringUTF("Test String");
732  env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0);
733  jni_abort_catcher.Check(
734      "attempt to release boolean primitive array elements with an object of type "
735      "java.lang.String");
736}
737TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
738  CheckJniAbortCatcher jni_abort_catcher;
739  jobject object = env_->NewStringUTF("Test String");
740  jboolean is_copy;
741  void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
742  jni_abort_catcher.Check("expected primitive array, given java.lang.String");
743  env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
744  jni_abort_catcher.Check("expected primitive array, given java.lang.String");
745}
746
747TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
748  CheckJniAbortCatcher jni_abort_catcher;
749  constexpr size_t kLength = 10;
750  jbooleanArray array = env_->NewBooleanArray(kLength);
751  ASSERT_TRUE(array != nullptr);
752  jboolean elements[kLength];
753  env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
754                           reinterpret_cast<jbyte*>(elements));
755  jni_abort_catcher.Check(
756      "attempt to get region of byte primitive array elements with an object of type boolean[]");
757  env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
758                            reinterpret_cast<jshort*>(elements));
759  jni_abort_catcher.Check(
760      "attempt to get region of short primitive array elements with an object of type boolean[]");
761  env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
762                           reinterpret_cast<jchar*>(elements));
763  jni_abort_catcher.Check(
764      "attempt to get region of char primitive array elements with an object of type boolean[]");
765  env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
766                          reinterpret_cast<jint*>(elements));
767  jni_abort_catcher.Check(
768      "attempt to get region of int primitive array elements with an object of type boolean[]");
769  env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
770                           reinterpret_cast<jlong*>(elements));
771  jni_abort_catcher.Check(
772      "attempt to get region of long primitive array elements with an object of type boolean[]");
773  env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
774                            reinterpret_cast<jfloat*>(elements));
775  jni_abort_catcher.Check(
776      "attempt to get region of float primitive array elements with an object of type boolean[]");
777  env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
778                           reinterpret_cast<jdouble*>(elements));
779  jni_abort_catcher.Check(
780      "attempt to get region of double primitive array elements with an object of type boolean[]");
781  jbyteArray array2 = env_->NewByteArray(10);
782  env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
783                              reinterpret_cast<jboolean*>(elements));
784  jni_abort_catcher.Check(
785      "attempt to get region of boolean primitive array elements with an object of type byte[]");
786  jobject object = env_->NewStringUTF("Test String");
787  env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
788                              reinterpret_cast<jboolean*>(elements));
789  jni_abort_catcher.Check(
790      "attempt to get region of boolean primitive array elements with an object of type "
791      "java.lang.String");
792}
793
794TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
795  CheckJniAbortCatcher jni_abort_catcher;
796  constexpr size_t kLength = 10;
797  jbooleanArray array = env_->NewBooleanArray(kLength);
798  ASSERT_TRUE(array != nullptr);
799  jboolean elements[kLength];
800  env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
801                           reinterpret_cast<jbyte*>(elements));
802  jni_abort_catcher.Check(
803      "attempt to set region of byte primitive array elements with an object of type boolean[]");
804  env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
805                            reinterpret_cast<jshort*>(elements));
806  jni_abort_catcher.Check(
807      "attempt to set region of short primitive array elements with an object of type boolean[]");
808  env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
809                           reinterpret_cast<jchar*>(elements));
810  jni_abort_catcher.Check(
811      "attempt to set region of char primitive array elements with an object of type boolean[]");
812  env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
813                          reinterpret_cast<jint*>(elements));
814  jni_abort_catcher.Check(
815      "attempt to set region of int primitive array elements with an object of type boolean[]");
816  env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
817                           reinterpret_cast<jlong*>(elements));
818  jni_abort_catcher.Check(
819      "attempt to set region of long primitive array elements with an object of type boolean[]");
820  env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
821                            reinterpret_cast<jfloat*>(elements));
822  jni_abort_catcher.Check(
823      "attempt to set region of float primitive array elements with an object of type boolean[]");
824  env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
825                           reinterpret_cast<jdouble*>(elements));
826  jni_abort_catcher.Check(
827      "attempt to set region of double primitive array elements with an object of type boolean[]");
828  jbyteArray array2 = env_->NewByteArray(10);
829  env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
830                              reinterpret_cast<jboolean*>(elements));
831  jni_abort_catcher.Check(
832      "attempt to set region of boolean primitive array elements with an object of type byte[]");
833  jobject object = env_->NewStringUTF("Test String");
834  env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
835                              reinterpret_cast<jboolean*>(elements));
836  jni_abort_catcher.Check(
837      "attempt to set region of boolean primitive array elements with an object of type "
838      "java.lang.String");
839}
840
841TEST_F(JniInternalTest, NewObjectArray) {
842  jclass element_class = env_->FindClass("java/lang/String");
843  ASSERT_NE(element_class, nullptr);
844  jclass array_class = env_->FindClass("[Ljava/lang/String;");
845  ASSERT_NE(array_class, nullptr);
846
847  jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
848  EXPECT_NE(a, nullptr);
849  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
850  EXPECT_EQ(0, env_->GetArrayLength(a));
851
852  a = env_->NewObjectArray(1, element_class, nullptr);
853  EXPECT_NE(a, nullptr);
854  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
855  EXPECT_EQ(1, env_->GetArrayLength(a));
856  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
857
858  // Negative array length checks.
859  CheckJniAbortCatcher jni_abort_catcher;
860  env_->NewObjectArray(-1, element_class, nullptr);
861  jni_abort_catcher.Check("negative array length: -1");
862
863  env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr);
864  jni_abort_catcher.Check("negative array length: -2147483648");
865}
866
867TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) {
868  const char* primitive_descriptors = "VZBSCIJFD";
869  const char* primitive_names[] = {
870      "void", "boolean", "byte", "short", "char", "int", "long", "float", "double"
871  };
872  ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names));
873
874  CheckJniAbortCatcher jni_abort_catcher;
875  for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
876    env_->NewObjectArray(0, nullptr, nullptr);
877    jni_abort_catcher.Check("element_jclass == null");
878    jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
879    env_->NewObjectArray(1, primitive_class, nullptr);
880    std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
881    jni_abort_catcher.Check(error_msg.c_str());
882  }
883}
884
885TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
886  jclass element_class = env_->FindClass("java/lang/String");
887  ASSERT_NE(element_class, nullptr);
888  jclass array_class = env_->FindClass("[Ljava/lang/String;");
889  ASSERT_NE(array_class, nullptr);
890
891  jstring s = env_->NewStringUTF("poop");
892  jobjectArray a = env_->NewObjectArray(2, element_class, s);
893  EXPECT_NE(a, nullptr);
894  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
895  EXPECT_EQ(2, env_->GetArrayLength(a));
896  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
897  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
898
899  // Attempt to incorrect create an array of strings with initial value of string arrays.
900  CheckJniAbortCatcher jni_abort_catcher;
901  env_->NewObjectArray(2, element_class, a);
902  jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element "
903                          "type of 'java.lang.String'");
904}
905
906TEST_F(JniInternalTest, GetArrayLength) {
907  // Already tested in NewObjectArray/NewPrimitiveArray.
908}
909
910TEST_F(JniInternalTest, GetObjectClass) {
911  jclass string_class = env_->FindClass("java/lang/String");
912  ASSERT_NE(string_class, nullptr);
913  jclass class_class = env_->FindClass("java/lang/Class");
914  ASSERT_NE(class_class, nullptr);
915
916  jstring s = env_->NewStringUTF("poop");
917  jclass c = env_->GetObjectClass(s);
918  ASSERT_TRUE(env_->IsSameObject(string_class, c));
919
920  jclass c2 = env_->GetObjectClass(c);
921  ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
922
923  // Null as object should fail.
924  CheckJniAbortCatcher jni_abort_catcher;
925  EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
926  jni_abort_catcher.Check("java_object == null");
927}
928
929TEST_F(JniInternalTest, GetSuperclass) {
930  jclass object_class = env_->FindClass("java/lang/Object");
931  ASSERT_NE(object_class, nullptr);
932  jclass string_class = env_->FindClass("java/lang/String");
933  ASSERT_NE(string_class, nullptr);
934  jclass runnable_interface = env_->FindClass("java/lang/Runnable");
935  ASSERT_NE(runnable_interface, nullptr);
936  ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
937  ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
938  ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
939
940  // Null as class should fail.
941  CheckJniAbortCatcher jni_abort_catcher;
942  EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
943  jni_abort_catcher.Check("java_class == null");
944}
945
946TEST_F(JniInternalTest, IsAssignableFrom) {
947  jclass object_class = env_->FindClass("java/lang/Object");
948  ASSERT_NE(object_class, nullptr);
949  jclass string_class = env_->FindClass("java/lang/String");
950  ASSERT_NE(string_class, nullptr);
951
952  // A superclass is assignable from an instance of its
953  // subclass but not vice versa.
954  ASSERT_TRUE(env_->IsAssignableFrom(string_class, object_class));
955  ASSERT_FALSE(env_->IsAssignableFrom(object_class, string_class));
956
957  jclass charsequence_interface = env_->FindClass("java/lang/CharSequence");
958  ASSERT_NE(charsequence_interface, nullptr);
959
960  // An interface is assignable from an instance of an implementing
961  // class but not vice versa.
962  ASSERT_TRUE(env_->IsAssignableFrom(string_class, charsequence_interface));
963  ASSERT_FALSE(env_->IsAssignableFrom(charsequence_interface, string_class));
964
965  // Check that arrays are covariant.
966  jclass string_array_class = env_->FindClass("[Ljava/lang/String;");
967  ASSERT_NE(string_array_class, nullptr);
968  jclass object_array_class = env_->FindClass("[Ljava/lang/Object;");
969  ASSERT_NE(object_array_class, nullptr);
970  ASSERT_TRUE(env_->IsAssignableFrom(string_array_class, object_array_class));
971  ASSERT_FALSE(env_->IsAssignableFrom(object_array_class, string_array_class));
972
973  // Primitive types are tested in 004-JniTest.
974
975  // Null as either class should fail.
976  CheckJniAbortCatcher jni_abort_catcher;
977  EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
978  jni_abort_catcher.Check("java_class1 == null");
979  EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
980  jni_abort_catcher.Check("java_class2 == null");
981}
982
983TEST_F(JniInternalTest, GetObjectRefType) {
984  jclass local = env_->FindClass("java/lang/Object");
985  ASSERT_TRUE(local != nullptr);
986  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
987
988  jobject global = env_->NewGlobalRef(local);
989  EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
990
991  jweak weak_global = env_->NewWeakGlobalRef(local);
992  EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
993
994  jobject invalid = reinterpret_cast<jobject>(this);
995  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
996
997  // TODO: invoke a native method and test that its arguments are considered local references.
998
999  // Null as object should fail.
1000  CheckJniAbortCatcher jni_abort_catcher;
1001  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
1002  jni_abort_catcher.Check("java_object == null");
1003}
1004
1005TEST_F(JniInternalTest, StaleWeakGlobal) {
1006  jclass java_lang_Class = env_->FindClass("java/lang/Class");
1007  ASSERT_NE(java_lang_Class, nullptr);
1008  jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
1009  ASSERT_NE(local_ref, nullptr);
1010  jweak weak_global = env_->NewWeakGlobalRef(local_ref);
1011  ASSERT_NE(weak_global, nullptr);
1012  env_->DeleteLocalRef(local_ref);
1013  Runtime::Current()->GetHeap()->CollectGarbage(false);  // GC should clear the weak global.
1014  jobject new_global_ref = env_->NewGlobalRef(weak_global);
1015  EXPECT_EQ(new_global_ref, nullptr);
1016  jobject new_local_ref = env_->NewLocalRef(weak_global);
1017  EXPECT_EQ(new_local_ref, nullptr);
1018}
1019
1020TEST_F(JniInternalTest, NewStringUTF) {
1021  EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
1022  jstring s;
1023
1024  s = env_->NewStringUTF("");
1025  EXPECT_NE(s, nullptr);
1026  EXPECT_EQ(0, env_->GetStringLength(s));
1027  EXPECT_EQ(0, env_->GetStringUTFLength(s));
1028  s = env_->NewStringUTF("hello");
1029  EXPECT_NE(s, nullptr);
1030  EXPECT_EQ(5, env_->GetStringLength(s));
1031  EXPECT_EQ(5, env_->GetStringUTFLength(s));
1032
1033  // TODO: check some non-ASCII strings.
1034}
1035
1036TEST_F(JniInternalTest, NewString) {
1037  jchar chars[] = { 'h', 'i' };
1038  jstring s;
1039  s = env_->NewString(chars, 0);
1040  EXPECT_NE(s, nullptr);
1041  EXPECT_EQ(0, env_->GetStringLength(s));
1042  EXPECT_EQ(0, env_->GetStringUTFLength(s));
1043  s = env_->NewString(chars, 2);
1044  EXPECT_NE(s, nullptr);
1045  EXPECT_EQ(2, env_->GetStringLength(s));
1046  EXPECT_EQ(2, env_->GetStringUTFLength(s));
1047
1048  // TODO: check some non-ASCII strings.
1049}
1050
1051TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
1052  jstring s = env_->NewString(nullptr, 0);
1053  EXPECT_NE(s, nullptr);
1054  EXPECT_EQ(0, env_->GetStringLength(s));
1055}
1056
1057TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) {
1058  CheckJniAbortCatcher jni_abort_catcher;
1059  env_->NewString(nullptr, 1);
1060  jni_abort_catcher.Check("chars == null && char_count > 0");
1061}
1062
1063TEST_F(JniInternalTest, NewStringNegativeLength) {
1064  CheckJniAbortCatcher jni_abort_catcher;
1065  env_->NewString(nullptr, -1);
1066  jni_abort_catcher.Check("char_count < 0: -1");
1067  env_->NewString(nullptr, std::numeric_limits<jint>::min());
1068  jni_abort_catcher.Check("char_count < 0: -2147483648");
1069}
1070
1071TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1072  // Already tested in the NewString/NewStringUTF tests.
1073}
1074
1075TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1076  jstring s = env_->NewStringUTF("hello");
1077  ASSERT_TRUE(s != nullptr);
1078
1079  env_->GetStringRegion(s, -1, 0, nullptr);
1080  ExpectException(sioobe_);
1081  env_->GetStringRegion(s, 0, -1, nullptr);
1082  ExpectException(sioobe_);
1083  env_->GetStringRegion(s, 0, 10, nullptr);
1084  ExpectException(sioobe_);
1085  env_->GetStringRegion(s, 10, 1, nullptr);
1086  ExpectException(sioobe_);
1087
1088  jchar chars[4] = { 'x', 'x', 'x', 'x' };
1089  env_->GetStringRegion(s, 1, 2, &chars[1]);
1090  EXPECT_EQ('x', chars[0]);
1091  EXPECT_EQ('e', chars[1]);
1092  EXPECT_EQ('l', chars[2]);
1093  EXPECT_EQ('x', chars[3]);
1094
1095  // It's okay for the buffer to be nullptr as long as the length is 0.
1096  env_->GetStringRegion(s, 2, 0, nullptr);
1097  // Even if the offset is invalid...
1098  env_->GetStringRegion(s, 123, 0, nullptr);
1099  ExpectException(sioobe_);
1100
1101  env_->GetStringUTFRegion(s, -1, 0, nullptr);
1102  ExpectException(sioobe_);
1103  env_->GetStringUTFRegion(s, 0, -1, nullptr);
1104  ExpectException(sioobe_);
1105  env_->GetStringUTFRegion(s, 0, 10, nullptr);
1106  ExpectException(sioobe_);
1107  env_->GetStringUTFRegion(s, 10, 1, nullptr);
1108  ExpectException(sioobe_);
1109
1110  char bytes[4] = { 'x', 'x', 'x', 'x' };
1111  env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1112  EXPECT_EQ('x', bytes[0]);
1113  EXPECT_EQ('e', bytes[1]);
1114  EXPECT_EQ('l', bytes[2]);
1115  EXPECT_EQ('x', bytes[3]);
1116
1117  // It's okay for the buffer to be nullptr as long as the length is 0.
1118  env_->GetStringUTFRegion(s, 2, 0, nullptr);
1119  // Even if the offset is invalid...
1120  env_->GetStringUTFRegion(s, 123, 0, nullptr);
1121  ExpectException(sioobe_);
1122}
1123
1124TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
1125  // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni.
1126  {
1127    CheckJniAbortCatcher check_jni_abort_catcher;
1128    EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
1129    check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
1130  }
1131
1132  jstring s = env_->NewStringUTF("hello");
1133  ASSERT_TRUE(s != nullptr);
1134
1135  const char* utf = env_->GetStringUTFChars(s, nullptr);
1136  EXPECT_STREQ("hello", utf);
1137  env_->ReleaseStringUTFChars(s, utf);
1138
1139  jboolean is_copy = JNI_FALSE;
1140  utf = env_->GetStringUTFChars(s, &is_copy);
1141  EXPECT_EQ(JNI_TRUE, is_copy);
1142  EXPECT_STREQ("hello", utf);
1143  env_->ReleaseStringUTFChars(s, utf);
1144}
1145
1146TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1147  jstring s = env_->NewStringUTF("hello");
1148  ScopedObjectAccess soa(env_);
1149  mirror::String* s_m = soa.Decode<mirror::String*>(s);
1150  ASSERT_TRUE(s != nullptr);
1151
1152  jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1153  const jchar* chars = env_->GetStringChars(s, nullptr);
1154  EXPECT_EQ(expected[0], chars[0]);
1155  EXPECT_EQ(expected[1], chars[1]);
1156  EXPECT_EQ(expected[2], chars[2]);
1157  EXPECT_EQ(expected[3], chars[3]);
1158  EXPECT_EQ(expected[4], chars[4]);
1159  env_->ReleaseStringChars(s, chars);
1160
1161  jboolean is_copy = JNI_FALSE;
1162  chars = env_->GetStringChars(s, &is_copy);
1163  if (Runtime::Current()->GetHeap()->IsMovableObject(s_m->GetCharArray())) {
1164    EXPECT_EQ(JNI_TRUE, is_copy);
1165  } else {
1166    EXPECT_EQ(JNI_FALSE, is_copy);
1167  }
1168  EXPECT_EQ(expected[0], chars[0]);
1169  EXPECT_EQ(expected[1], chars[1]);
1170  EXPECT_EQ(expected[2], chars[2]);
1171  EXPECT_EQ(expected[3], chars[3]);
1172  EXPECT_EQ(expected[4], chars[4]);
1173  env_->ReleaseStringChars(s, chars);
1174}
1175
1176TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1177  jstring s = env_->NewStringUTF("hello");
1178  ASSERT_TRUE(s != nullptr);
1179
1180  jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1181  const jchar* chars = env_->GetStringCritical(s, nullptr);
1182  EXPECT_EQ(expected[0], chars[0]);
1183  EXPECT_EQ(expected[1], chars[1]);
1184  EXPECT_EQ(expected[2], chars[2]);
1185  EXPECT_EQ(expected[3], chars[3]);
1186  EXPECT_EQ(expected[4], chars[4]);
1187  env_->ReleaseStringCritical(s, chars);
1188
1189  jboolean is_copy = JNI_TRUE;
1190  chars = env_->GetStringCritical(s, &is_copy);
1191  EXPECT_EQ(JNI_FALSE, is_copy);
1192  EXPECT_EQ(expected[0], chars[0]);
1193  EXPECT_EQ(expected[1], chars[1]);
1194  EXPECT_EQ(expected[2], chars[2]);
1195  EXPECT_EQ(expected[3], chars[3]);
1196  EXPECT_EQ(expected[4], chars[4]);
1197  env_->ReleaseStringCritical(s, chars);
1198}
1199
1200TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
1201  jclass java_lang_Class = env_->FindClass("java/lang/Class");
1202  ASSERT_TRUE(java_lang_Class != nullptr);
1203
1204  jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
1205  EXPECT_NE(array, nullptr);
1206  EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
1207  env_->SetObjectArrayElement(array, 0, java_lang_Class);
1208  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
1209
1210  // ArrayIndexOutOfBounds for negative index.
1211  env_->SetObjectArrayElement(array, -1, java_lang_Class);
1212  ExpectException(aioobe_);
1213
1214  // ArrayIndexOutOfBounds for too-large index.
1215  env_->SetObjectArrayElement(array, 1, java_lang_Class);
1216  ExpectException(aioobe_);
1217
1218  // ArrayStoreException thrown for bad types.
1219  env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
1220  ExpectException(ase_);
1221
1222  // Null as array should fail.
1223  CheckJniAbortCatcher jni_abort_catcher;
1224  EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1225  jni_abort_catcher.Check("java_array == null");
1226  env_->SetObjectArrayElement(nullptr, 0, nullptr);
1227  jni_abort_catcher.Check("java_array == null");
1228}
1229
1230#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
1231  do { \
1232    jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1233    EXPECT_NE(fid, nullptr); \
1234    env_->SetStatic ## type ## Field(c, fid, value1); \
1235    EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
1236    env_->SetStatic ## type ## Field(c, fid, value2); \
1237    EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
1238    \
1239    CheckJniAbortCatcher jni_abort_catcher; \
1240    env_->GetStatic ## type ## Field(nullptr, fid); \
1241    jni_abort_catcher.Check("received null jclass"); \
1242    env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1243    jni_abort_catcher.Check("received null jclass"); \
1244    env_->GetStatic ## type ## Field(c, nullptr); \
1245    jni_abort_catcher.Check("fid == null"); \
1246    env_->SetStatic ## type ## Field(c, nullptr, value1); \
1247    jni_abort_catcher.Check("fid == null"); \
1248  } while (false)
1249
1250#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
1251  do { \
1252    jfieldID fid = env_->GetFieldID(c, field_name, sig); \
1253    EXPECT_NE(fid, nullptr); \
1254    env_->Set ## type ## Field(instance, fid, value1); \
1255    EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
1256    env_->Set ## type ## Field(instance, fid, value2); \
1257    EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
1258    \
1259    CheckJniAbortCatcher jni_abort_catcher; \
1260    env_->Get ## type ## Field(nullptr, fid); \
1261    jni_abort_catcher.Check("obj == null"); \
1262    env_->Set ## type ## Field(nullptr, fid, value1); \
1263    jni_abort_catcher.Check("obj == null"); \
1264    env_->Get ## type ## Field(instance, nullptr); \
1265    jni_abort_catcher.Check("fid == null"); \
1266    env_->Set ## type ## Field(instance, nullptr, value1); \
1267    jni_abort_catcher.Check("fid == null"); \
1268  } while (false)
1269
1270
1271TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
1272  TEST_DISABLED_FOR_PORTABLE();
1273  Thread::Current()->TransitionFromSuspendedToRunnable();
1274  LoadDex("AllFields");
1275  bool started = runtime_->Start();
1276  ASSERT_TRUE(started);
1277
1278  jclass c = env_->FindClass("AllFields");
1279  ASSERT_NE(c, nullptr);
1280  jobject o = env_->AllocObject(c);
1281  ASSERT_NE(o, nullptr);
1282
1283  EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
1284  EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
1285  EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
1286  EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
1287  EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
1288  EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
1289  EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
1290  EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
1291
1292  EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
1293  EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
1294  EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
1295  EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
1296  EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
1297  EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
1298  EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
1299  EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
1300}
1301
1302TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
1303  TEST_DISABLED_FOR_PORTABLE();
1304  Thread::Current()->TransitionFromSuspendedToRunnable();
1305  LoadDex("AllFields");
1306  runtime_->Start();
1307
1308  jclass c = env_->FindClass("AllFields");
1309  ASSERT_NE(c, nullptr);
1310  jobject o = env_->AllocObject(c);
1311  ASSERT_NE(o, nullptr);
1312
1313  jstring s1 = env_->NewStringUTF("hello");
1314  ASSERT_NE(s1, nullptr);
1315  jstring s2 = env_->NewStringUTF("world");
1316  ASSERT_NE(s2, nullptr);
1317
1318  jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
1319  ASSERT_NE(s_fid, nullptr);
1320  jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
1321  ASSERT_NE(i_fid, nullptr);
1322
1323  env_->SetStaticObjectField(c, s_fid, s1);
1324  ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
1325  env_->SetStaticObjectField(c, s_fid, s2);
1326  ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
1327
1328  env_->SetObjectField(o, i_fid, s1);
1329  ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
1330  env_->SetObjectField(o, i_fid, s2);
1331  ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
1332}
1333
1334TEST_F(JniInternalTest, NewLocalRef_nullptr) {
1335  EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
1336}
1337
1338TEST_F(JniInternalTest, NewLocalRef) {
1339  jstring s = env_->NewStringUTF("");
1340  ASSERT_NE(s, nullptr);
1341  jobject o = env_->NewLocalRef(s);
1342  EXPECT_NE(o, nullptr);
1343  EXPECT_NE(o, s);
1344
1345  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
1346}
1347
1348TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
1349  env_->DeleteLocalRef(nullptr);
1350}
1351
1352TEST_F(JniInternalTest, DeleteLocalRef) {
1353  jstring s = env_->NewStringUTF("");
1354  ASSERT_NE(s, nullptr);
1355  env_->DeleteLocalRef(s);
1356
1357  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1358  {
1359    CheckJniAbortCatcher check_jni_abort_catcher;
1360    env_->DeleteLocalRef(s);
1361
1362    std::string expected(StringPrintf("native code passing in reference to "
1363                                      "invalid local reference: %p", s));
1364    check_jni_abort_catcher.Check(expected.c_str());
1365  }
1366
1367  s = env_->NewStringUTF("");
1368  ASSERT_NE(s, nullptr);
1369  jobject o = env_->NewLocalRef(s);
1370  ASSERT_NE(o, nullptr);
1371
1372  env_->DeleteLocalRef(s);
1373  env_->DeleteLocalRef(o);
1374}
1375
1376TEST_F(JniInternalTest, PushLocalFrame_10395422) {
1377  // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
1378  // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
1379  // Android historically treated it, and it's how the RI treats it. It's also the more useful
1380  // interpretation!
1381  ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
1382  env_->PopLocalFrame(nullptr);
1383
1384  // Negative capacities are not allowed.
1385  ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
1386
1387  // And it's okay to have an upper limit. Ours is currently 512.
1388  ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192));
1389}
1390
1391TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
1392  jobject original = env_->NewStringUTF("");
1393  ASSERT_NE(original, nullptr);
1394
1395  jobject outer;
1396  jobject inner1, inner2;
1397  ScopedObjectAccess soa(env_);
1398  mirror::Object* inner2_direct_pointer;
1399  {
1400    ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
1401    outer = env_->NewLocalRef(original);
1402
1403    {
1404      ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
1405      inner1 = env_->NewLocalRef(outer);
1406      inner2 = env_->NewStringUTF("survivor");
1407      inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2);
1408      env_->PopLocalFrame(inner2);
1409    }
1410
1411    EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1412    EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
1413    EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1414
1415    // Our local reference for the survivor is invalid because the survivor
1416    // gets a new local reference...
1417    EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1418
1419    env_->PopLocalFrame(nullptr);
1420  }
1421  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1422  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1423  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1424  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1425}
1426
1427TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
1428  EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
1429}
1430
1431TEST_F(JniInternalTest, NewGlobalRef) {
1432  jstring s = env_->NewStringUTF("");
1433  ASSERT_NE(s, nullptr);
1434  jobject o = env_->NewGlobalRef(s);
1435  EXPECT_NE(o, nullptr);
1436  EXPECT_NE(o, s);
1437
1438  EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
1439}
1440
1441TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
1442  env_->DeleteGlobalRef(nullptr);
1443}
1444
1445TEST_F(JniInternalTest, DeleteGlobalRef) {
1446  jstring s = env_->NewStringUTF("");
1447  ASSERT_NE(s, nullptr);
1448
1449  jobject o = env_->NewGlobalRef(s);
1450  ASSERT_NE(o, nullptr);
1451  env_->DeleteGlobalRef(o);
1452
1453  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1454  {
1455    CheckJniAbortCatcher check_jni_abort_catcher;
1456    env_->DeleteGlobalRef(o);
1457
1458    std::string expected(StringPrintf("native code passing in reference to "
1459                                      "invalid global reference: %p", o));
1460    check_jni_abort_catcher.Check(expected.c_str());
1461  }
1462
1463  jobject o1 = env_->NewGlobalRef(s);
1464  ASSERT_NE(o1, nullptr);
1465  jobject o2 = env_->NewGlobalRef(s);
1466  ASSERT_NE(o2, nullptr);
1467
1468  env_->DeleteGlobalRef(o1);
1469  env_->DeleteGlobalRef(o2);
1470}
1471
1472TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
1473  EXPECT_EQ(env_->NewWeakGlobalRef(nullptr),   nullptr);
1474}
1475
1476TEST_F(JniInternalTest, NewWeakGlobalRef) {
1477  jstring s = env_->NewStringUTF("");
1478  ASSERT_NE(s, nullptr);
1479  jobject o = env_->NewWeakGlobalRef(s);
1480  EXPECT_NE(o, nullptr);
1481  EXPECT_NE(o, s);
1482
1483  EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
1484}
1485
1486TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
1487  env_->DeleteWeakGlobalRef(nullptr);
1488}
1489
1490TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1491  jstring s = env_->NewStringUTF("");
1492  ASSERT_NE(s, nullptr);
1493
1494  jobject o = env_->NewWeakGlobalRef(s);
1495  ASSERT_NE(o, nullptr);
1496  env_->DeleteWeakGlobalRef(o);
1497
1498  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1499  {
1500    CheckJniAbortCatcher check_jni_abort_catcher;
1501    env_->DeleteWeakGlobalRef(o);
1502
1503    std::string expected(StringPrintf("native code passing in reference to "
1504                                      "invalid weak global reference: %p", o));
1505    check_jni_abort_catcher.Check(expected.c_str());
1506  }
1507
1508  jobject o1 = env_->NewWeakGlobalRef(s);
1509  ASSERT_NE(o1, nullptr);
1510  jobject o2 = env_->NewWeakGlobalRef(s);
1511  ASSERT_NE(o2, nullptr);
1512
1513  env_->DeleteWeakGlobalRef(o1);
1514  env_->DeleteWeakGlobalRef(o2);
1515}
1516
1517TEST_F(JniInternalTest, ExceptionDescribe) {
1518  // This checks how ExceptionDescribe handles call without exception.
1519  env_->ExceptionClear();
1520  env_->ExceptionDescribe();
1521}
1522
1523TEST_F(JniInternalTest, Throw) {
1524  EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
1525
1526  jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1527  ASSERT_TRUE(exception_class != nullptr);
1528  jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
1529  ASSERT_TRUE(exception != nullptr);
1530
1531  EXPECT_EQ(JNI_OK, env_->Throw(exception));
1532  EXPECT_TRUE(env_->ExceptionCheck());
1533  jthrowable thrown_exception = env_->ExceptionOccurred();
1534  env_->ExceptionClear();
1535  EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
1536}
1537
1538TEST_F(JniInternalTest, ThrowNew) {
1539  EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
1540
1541  jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1542  ASSERT_TRUE(exception_class != nullptr);
1543
1544  jthrowable thrown_exception;
1545
1546  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1547  EXPECT_TRUE(env_->ExceptionCheck());
1548  thrown_exception = env_->ExceptionOccurred();
1549  env_->ExceptionClear();
1550  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1551
1552  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
1553  EXPECT_TRUE(env_->ExceptionCheck());
1554  thrown_exception = env_->ExceptionOccurred();
1555  env_->ExceptionClear();
1556  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1557}
1558
1559TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1560  // Start runtime.
1561  Thread* self = Thread::Current();
1562  self->TransitionFromSuspendedToRunnable();
1563  MakeExecutable(nullptr, "java.lang.Class");
1564  MakeExecutable(nullptr, "java.lang.Object");
1565  MakeExecutable(nullptr, "java.nio.DirectByteBuffer");
1566  MakeExecutable(nullptr, "java.nio.MemoryBlock");
1567  MakeExecutable(nullptr, "java.nio.MemoryBlock$UnmanagedBlock");
1568  MakeExecutable(nullptr, "java.nio.MappedByteBuffer");
1569  MakeExecutable(nullptr, "java.nio.ByteBuffer");
1570  MakeExecutable(nullptr, "java.nio.Buffer");
1571  // TODO: we only load a dex file here as starting the runtime relies upon it.
1572  const char* class_name = "StaticLeafMethods";
1573  LoadDex(class_name);
1574  bool started = runtime_->Start();
1575  ASSERT_TRUE(started);
1576
1577  jclass buffer_class = env_->FindClass("java/nio/Buffer");
1578  ASSERT_NE(buffer_class, nullptr);
1579
1580  char bytes[1024];
1581  jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
1582  ASSERT_NE(buffer, nullptr);
1583  ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
1584  ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
1585  ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
1586
1587  {
1588    CheckJniAbortCatcher check_jni_abort_catcher;
1589    env_->NewDirectByteBuffer(bytes, static_cast<jlong>(INT_MAX) + 1);
1590    check_jni_abort_catcher.Check("in call to NewDirectByteBuffer");
1591  }
1592}
1593
1594TEST_F(JniInternalTest, MonitorEnterExit) {
1595  // Create an object to torture.
1596  jclass object_class = env_->FindClass("java/lang/Object");
1597  ASSERT_NE(object_class, nullptr);
1598  jobject object = env_->AllocObject(object_class);
1599  ASSERT_NE(object, nullptr);
1600
1601  // Expected class of exceptions
1602  jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
1603  ASSERT_NE(imse_class, nullptr);
1604
1605  jthrowable thrown_exception;
1606
1607  // Unlock of unowned monitor
1608  env_->MonitorExit(object);
1609  EXPECT_TRUE(env_->ExceptionCheck());
1610  thrown_exception = env_->ExceptionOccurred();
1611  env_->ExceptionClear();
1612  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1613
1614  // Lock of unowned monitor
1615  env_->MonitorEnter(object);
1616  EXPECT_FALSE(env_->ExceptionCheck());
1617  // Regular unlock
1618  env_->MonitorExit(object);
1619  EXPECT_FALSE(env_->ExceptionCheck());
1620
1621  // Recursively lock a lot
1622  size_t max_recursive_lock = 1024;
1623  for (size_t i = 0; i < max_recursive_lock; i++) {
1624    env_->MonitorEnter(object);
1625    EXPECT_FALSE(env_->ExceptionCheck());
1626  }
1627  // Recursively unlock a lot
1628  for (size_t i = 0; i < max_recursive_lock; i++) {
1629    env_->MonitorExit(object);
1630    EXPECT_FALSE(env_->ExceptionCheck());
1631  }
1632
1633  // Unlock of unowned monitor
1634  env_->MonitorExit(object);
1635  EXPECT_TRUE(env_->ExceptionCheck());
1636  thrown_exception = env_->ExceptionOccurred();
1637  env_->ExceptionClear();
1638  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1639
1640  // It's an error to call MonitorEnter or MonitorExit on nullptr.
1641  {
1642    CheckJniAbortCatcher check_jni_abort_catcher;
1643    env_->MonitorEnter(nullptr);
1644    check_jni_abort_catcher.Check("in call to MonitorEnter");
1645    env_->MonitorExit(nullptr);
1646    check_jni_abort_catcher.Check("in call to MonitorExit");
1647  }
1648}
1649
1650TEST_F(JniInternalTest, DetachCurrentThread) {
1651  CleanUpJniEnv();  // cleanup now so TearDown won't have junk from wrong JNIEnv
1652  jint ok = vm_->DetachCurrentThread();
1653  EXPECT_EQ(JNI_OK, ok);
1654
1655  jint err = vm_->DetachCurrentThread();
1656  EXPECT_EQ(JNI_ERR, err);
1657  vm_->AttachCurrentThread(&env_, nullptr);  // need attached thread for CommonRuntimeTest::TearDown
1658}
1659
1660}  // namespace art
1661