blob: 7b29a9cd4397f5cb0aa500e1dc679d5de8d19525 [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
Ian Rogers1d54e732013-05-02 21:10:01 -070019#include <limits.h>
Elliott Hughesf66330a2012-12-12 17:27:00 -080020#include <cfloat>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070021#include <cmath>
22
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080023#include "common_compiler_test.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070024#include "mirror/art_method-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070025#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "mirror/object_array-inl.h"
Ian Rogers04d7aa92013-03-16 14:29:17 -070027#include "mirror/object-inl.h"
Elliott Hughes726079d2011-10-07 18:43:44 -070028#include "ScopedLocalRef.h"
Ian Rogers1f539342012-10-03 21:09:42 -070029#include "sirt_ref.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070030
31namespace art {
32
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080033// TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used.
34class JniInternalTest : public CommonCompilerTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070035 protected:
36 virtual void SetUp() {
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080037 CommonCompilerTest::SetUp();
Elliott Hughes5174fe62011-08-23 15:12:35 -070038
Elliott Hughesa2501992011-08-26 19:39:54 -070039 vm_ = Runtime::Current()->GetJavaVM();
40
Elliott Hughes5174fe62011-08-23 15:12:35 -070041 // Turn on -verbose:jni for the JNI tests.
Ian Rogers79713632013-08-21 19:06:15 -070042 // gLogVerbosity.jni = true;
Elliott Hughes5174fe62011-08-23 15:12:35 -070043
Brian Carlstrom4d571432012-05-16 00:21:41 -070044 vm_->AttachCurrentThread(&env_, NULL);
Elliott Hughesb465ab02011-08-24 11:21:21 -070045
Brian Carlstromea46f952013-07-30 01:26:50 -070046 ScopedLocalRef<jclass> aioobe(env_,
47 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
Elliott Hughes726079d2011-10-07 18:43:44 -070048 CHECK(aioobe.get() != NULL);
49 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
Elliott Hughesb465ab02011-08-24 11:21:21 -070050
Elliott Hughesb264f082012-04-06 17:10:10 -070051 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
52 CHECK(ase.get() != NULL);
53 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
54
Brian Carlstromea46f952013-07-30 01:26:50 -070055 ScopedLocalRef<jclass> sioobe(env_,
56 env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
Elliott Hughes726079d2011-10-07 18:43:44 -070057 CHECK(sioobe.get() != NULL);
58 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
59 }
60
Brian Carlstrom4d571432012-05-16 00:21:41 -070061 void CleanUpJniEnv() {
62 if (aioobe_ != NULL) {
63 env_->DeleteGlobalRef(aioobe_);
64 aioobe_ = NULL;
65 }
66 if (ase_ != NULL) {
67 env_->DeleteGlobalRef(ase_);
68 ase_ = NULL;
69 }
70 if (sioobe_ != NULL) {
71 env_->DeleteGlobalRef(sioobe_);
72 sioobe_ = NULL;
73 }
74 }
75
Ian Rogers53b8b092014-03-13 23:45:53 -070076 virtual void TearDown() OVERRIDE {
Brian Carlstrom4d571432012-05-16 00:21:41 -070077 CleanUpJniEnv();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080078 CommonCompilerTest::TearDown();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070079 }
Elliott Hughesb465ab02011-08-24 11:21:21 -070080
Ian Rogers1d99e452014-01-02 17:36:41 -080081 jclass GetPrimitiveClass(char descriptor) {
82 ScopedObjectAccess soa(env_);
83 mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
84 CHECK(c != nullptr);
85 return soa.AddLocalReference<jclass>(c);
86 }
87
Elliott Hughesa2501992011-08-26 19:39:54 -070088 JavaVMExt* vm_;
Brian Carlstrom4d571432012-05-16 00:21:41 -070089 JNIEnv* env_;
Elliott Hughes814e4032011-08-23 12:07:56 -070090 jclass aioobe_;
Elliott Hughesb264f082012-04-06 17:10:10 -070091 jclass ase_;
Elliott Hughesb465ab02011-08-24 11:21:21 -070092 jclass sioobe_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -070093};
94
Elliott Hughes885c3bd2011-08-22 16:59:20 -070095TEST_F(JniInternalTest, AllocObject) {
96 jclass c = env_->FindClass("java/lang/String");
97 ASSERT_TRUE(c != NULL);
98 jobject o = env_->AllocObject(c);
99 ASSERT_TRUE(o != NULL);
100
101 // We have an instance of the class we asked for...
102 ASSERT_TRUE(env_->IsInstanceOf(o, c));
103 // ...whose fields haven't been initialized because
104 // we didn't call a constructor.
105 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
106 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
107 ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
108}
109
Elliott Hughesc7ac37f2011-08-12 12:21:58 -0700110TEST_F(JniInternalTest, GetVersion) {
111 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
112}
113
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700114#define EXPECT_CLASS_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700115 EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
116 EXPECT_FALSE(env_->ExceptionCheck())
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700117
118#define EXPECT_CLASS_NOT_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700119 EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
120 EXPECT_TRUE(env_->ExceptionCheck()); \
121 env_->ExceptionClear()
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700122
123TEST_F(JniInternalTest, FindClass) {
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700124 // Reference types...
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700125 EXPECT_CLASS_FOUND("java/lang/String");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700126 // ...for arrays too, where you must include "L;".
127 EXPECT_CLASS_FOUND("[Ljava/lang/String;");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700128 // Primitive arrays are okay too, if the primitive type is valid.
129 EXPECT_CLASS_FOUND("[C");
Elliott Hughesa2501992011-08-26 19:39:54 -0700130
Elliott Hughesb264f082012-04-06 17:10:10 -0700131 {
Elliott Hughesb264f082012-04-06 17:10:10 -0700132 // We support . as well as / for compatibility, if -Xcheck:jni is off.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700133 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughesb264f082012-04-06 17:10:10 -0700134 EXPECT_CLASS_FOUND("java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700135 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700136 EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700137 check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700138 EXPECT_CLASS_FOUND("[Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700139 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700140 EXPECT_CLASS_NOT_FOUND("[java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700141 check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700142
143 // You can't include the "L;" in a JNI class descriptor.
144 EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700145 check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700146
Elliott Hughesb264f082012-04-06 17:10:10 -0700147 // But you must include it for an array of any reference type.
148 EXPECT_CLASS_NOT_FOUND("[java/lang/String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700149 check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700150
151 EXPECT_CLASS_NOT_FOUND("[K");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700152 check_jni_abort_catcher.Check("illegal class name '[K'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700153 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700154
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700155 // But primitive types aren't allowed...
156 EXPECT_CLASS_NOT_FOUND("C");
157 EXPECT_CLASS_NOT_FOUND("K");
158}
159
Elliott Hughescdf53122011-08-19 15:46:09 -0700160#define EXPECT_EXCEPTION(exception_class) \
161 do { \
162 EXPECT_TRUE(env_->ExceptionCheck()); \
163 jthrowable exception = env_->ExceptionOccurred(); \
164 EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700165 env_->ExceptionClear(); \
Elliott Hughesa2501992011-08-26 19:39:54 -0700166 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700167 } while (false)
168
169TEST_F(JniInternalTest, GetFieldID) {
170 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
171 ASSERT_TRUE(jlnsfe != NULL);
172 jclass c = env_->FindClass("java/lang/String");
173 ASSERT_TRUE(c != NULL);
174
175 // Wrong type.
176 jfieldID fid = env_->GetFieldID(c, "count", "J");
177 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
178 EXPECT_EXCEPTION(jlnsfe);
179
Ian Rogersb17d08b2011-09-02 16:16:49 -0700180 // Wrong type where type doesn't exist.
181 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
182 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
183 EXPECT_EXCEPTION(jlnsfe);
184
Elliott Hughescdf53122011-08-19 15:46:09 -0700185 // Wrong name.
186 fid = env_->GetFieldID(c, "Count", "I");
187 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
188 EXPECT_EXCEPTION(jlnsfe);
189
190 // Good declared field lookup.
191 fid = env_->GetFieldID(c, "count", "I");
192 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
193 EXPECT_TRUE(fid != NULL);
194 EXPECT_FALSE(env_->ExceptionCheck());
195
196 // Good superclass field lookup.
197 c = env_->FindClass("java/lang/StringBuilder");
198 fid = env_->GetFieldID(c, "count", "I");
199 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
200 EXPECT_TRUE(fid != NULL);
201 EXPECT_FALSE(env_->ExceptionCheck());
202
203 // Not instance.
204 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
205 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
206 EXPECT_EXCEPTION(jlnsfe);
207}
208
209TEST_F(JniInternalTest, GetStaticFieldID) {
210 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
211 ASSERT_TRUE(jlnsfe != NULL);
212 jclass c = env_->FindClass("java/lang/String");
213 ASSERT_TRUE(c != NULL);
214
215 // Wrong type.
216 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
217 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
218 EXPECT_EXCEPTION(jlnsfe);
219
Ian Rogersb17d08b2011-09-02 16:16:49 -0700220 // Wrong type where type doesn't exist.
221 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
222 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
223 EXPECT_EXCEPTION(jlnsfe);
224
Elliott Hughescdf53122011-08-19 15:46:09 -0700225 // Wrong name.
226 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
227 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
228 EXPECT_EXCEPTION(jlnsfe);
229
230 // Good declared field lookup.
231 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
232 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
233 EXPECT_TRUE(fid != NULL);
234 EXPECT_FALSE(env_->ExceptionCheck());
235
236 // Not static.
237 fid = env_->GetStaticFieldID(c, "count", "I");
238 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
239 EXPECT_EXCEPTION(jlnsfe);
240}
241
Ian Rogers4dd71f12011-08-16 14:16:02 -0700242TEST_F(JniInternalTest, GetMethodID) {
243 jclass jlobject = env_->FindClass("java/lang/Object");
244 jclass jlstring = env_->FindClass("java/lang/String");
245 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
246
247 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700248 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700249
250 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
251 // a pending exception
252 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
253 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700254 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700255
256 // Check that java.lang.Object.equals() does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700257 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
258 EXPECT_NE(static_cast<jmethodID>(NULL), method);
259 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700260
261 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
262 // method is static
263 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
264 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700265 EXPECT_EXCEPTION(jlnsme);
Brian Carlstromea46f952013-07-30 01:26:50 -0700266
267 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor
268 method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
269 EXPECT_NE(static_cast<jmethodID>(NULL), method);
270 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700271}
272
273TEST_F(JniInternalTest, GetStaticMethodID) {
274 jclass jlobject = env_->FindClass("java/lang/Object");
275 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
276
277 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700278 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700279
280 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
281 // a pending exception
282 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
283 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700284 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700285
286 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
287 // the method is not static
288 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
289 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700290 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700291
292 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700293 jclass jlstring = env_->FindClass("java/lang/String");
294 method = env_->GetStaticMethodID(jlstring, "valueOf",
295 "(I)Ljava/lang/String;");
296 EXPECT_NE(static_cast<jmethodID>(NULL), method);
297 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700298}
299
Elliott Hughescdf53122011-08-19 15:46:09 -0700300TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
301 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
302 jclass c = env_->FindClass("java/lang/String");
303 ASSERT_TRUE(c != NULL);
304 jfieldID fid = env_->GetFieldID(c, "count", "I");
305 ASSERT_TRUE(fid != NULL);
306 // Turn the fid into a java.lang.reflect.Field...
307 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
308 ASSERT_TRUE(c != NULL);
309 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
310 // ...and back again.
311 jfieldID fid2 = env_->FromReflectedField(field);
312 ASSERT_TRUE(fid2 != NULL);
Brian Carlstromea46f952013-07-30 01:26:50 -0700313 // Make sure we can actually use it.
314 jstring s = env_->NewStringUTF("poop");
315 ASSERT_EQ(4, env_->GetIntField(s, fid2));
Elliott Hughescdf53122011-08-19 15:46:09 -0700316}
317
318TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
319 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
320 jclass c = env_->FindClass("java/lang/String");
321 ASSERT_TRUE(c != NULL);
322 jmethodID mid = env_->GetMethodID(c, "length", "()I");
323 ASSERT_TRUE(mid != NULL);
324 // Turn the mid into a java.lang.reflect.Method...
325 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
326 ASSERT_TRUE(c != NULL);
327 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
328 // ...and back again.
329 jmethodID mid2 = env_->FromReflectedMethod(method);
330 ASSERT_TRUE(mid2 != NULL);
Brian Carlstromea46f952013-07-30 01:26:50 -0700331 // Make sure we can actually use it.
332 jstring s = env_->NewStringUTF("poop");
333 // TODO: this should return 4, but the runtime skips the method
334 // invoke because the runtime isn't started. In the future it would
335 // be nice to use interpretter for things like this. This still does
336 // validate that we have a sane jmethodID value.
337 ASSERT_EQ(0, env_->CallIntMethod(s, mid2));
Elliott Hughescdf53122011-08-19 15:46:09 -0700338}
339
Elliott Hughes5174fe62011-08-23 15:12:35 -0700340void BogusMethod() {
341 // You can't pass NULL function pointers to RegisterNatives.
342}
343
Ian Rogers4dd71f12011-08-16 14:16:02 -0700344TEST_F(JniInternalTest, RegisterNatives) {
345 jclass jlobject = env_->FindClass("java/lang/Object");
346 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
347
348 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700349 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700350
351 // Check that registering to a non-existent java.lang.Object.foo() causes a
352 // NoSuchMethodError
353 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700354 JNINativeMethod methods[] = { { "foo", "()V", NULL } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700355 env_->RegisterNatives(jlobject, methods, 1);
356 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700357 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700358
359 // Check that registering non-native methods causes a NoSuchMethodError
360 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700361 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700362 env_->RegisterNatives(jlobject, methods, 1);
363 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700364 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700365
366 // Check that registering native methods is successful
367 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700368 JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700369 env_->RegisterNatives(jlobject, methods, 1);
370 }
371 EXPECT_FALSE(env_->ExceptionCheck());
Elliott Hughes5174fe62011-08-23 15:12:35 -0700372
373 env_->UnregisterNatives(jlobject);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700374}
375
Brian Carlstromea46f952013-07-30 01:26:50 -0700376#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
377 get_region_fn, \
378 set_region_fn, \
379 get_elements_fn, \
380 release_elements_fn, \
381 scalar_type, \
382 expected_class_descriptor) \
Ian Rogers1d99e452014-01-02 17:36:41 -0800383 { \
384 CheckJniAbortCatcher jni_abort_catcher; \
385 /* Allocate an negative sized array and check it has the right failure type. */ \
386 env_->new_fn(-1); \
387 jni_abort_catcher.Check("negative array length: -1"); \
388 env_->new_fn(std::numeric_limits<jint>::min()); \
389 jni_abort_catcher.Check("negative array length: -2147483648"); \
390 } \
Elliott Hughes814e4032011-08-23 12:07:56 -0700391 jsize size = 4; \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700392 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700393 /* Allocate an array and check it has the right type and length. */ \
394 scalar_type ## Array a = env_->new_fn(size); \
395 EXPECT_TRUE(a != NULL); \
396 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
397 EXPECT_EQ(size, env_->GetArrayLength(a)); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700398 \
399 /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
Elliott Hughes814e4032011-08-23 12:07:56 -0700400 /* AIOOBE for negative start offset. */ \
401 env_->get_region_fn(a, -1, 1, NULL); \
402 EXPECT_EXCEPTION(aioobe_); \
403 env_->set_region_fn(a, -1, 1, NULL); \
404 EXPECT_EXCEPTION(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700405 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700406 /* AIOOBE for negative length. */ \
407 env_->get_region_fn(a, 0, -1, NULL); \
408 EXPECT_EXCEPTION(aioobe_); \
409 env_->set_region_fn(a, 0, -1, NULL); \
410 EXPECT_EXCEPTION(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700411 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700412 /* AIOOBE for buffer overrun. */ \
413 env_->get_region_fn(a, size - 1, size, NULL); \
414 EXPECT_EXCEPTION(aioobe_); \
415 env_->set_region_fn(a, size - 1, size, NULL); \
416 EXPECT_EXCEPTION(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700417 \
418 /* It's okay for the buffer to be NULL as long as the length is 0. */ \
419 env_->get_region_fn(a, 2, 0, NULL); \
420 /* Even if the offset is invalid... */ \
421 env_->get_region_fn(a, 123, 0, NULL); \
422 EXPECT_EXCEPTION(aioobe_); \
423 \
424 /* It's okay for the buffer to be NULL as long as the length is 0. */ \
425 env_->set_region_fn(a, 2, 0, NULL); \
426 /* Even if the offset is invalid... */ \
427 env_->set_region_fn(a, 123, 0, NULL); \
428 EXPECT_EXCEPTION(aioobe_); \
429 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700430 /* Prepare a couple of buffers. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700431 UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
432 UniquePtr<scalar_type[]> dst_buf(new scalar_type[size]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700433 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
434 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700435 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700436 /* Copy all of src_buf onto the heap. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700437 env_->set_region_fn(a, 0, size, &src_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700438 /* Copy back only part. */ \
439 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700440 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
441 << "short copy equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700442 /* Copy the missing pieces. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700443 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700444 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700445 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
446 << "fixed copy not equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700447 /* Copy back the whole array. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700448 env_->get_region_fn(a, 0, size, &dst_buf[0]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700449 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
450 << "full copy not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700451 /* GetPrimitiveArrayCritical */ \
452 void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700453 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
454 << "GetPrimitiveArrayCritical not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700455 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
456 /* GetXArrayElements */ \
457 scalar_type* xs = env_->get_elements_fn(a, NULL); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700458 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
459 << # get_elements_fn " not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700460 env_->release_elements_fn(a, xs, 0); \
Elliott Hughesbd935992011-08-22 11:59:34 -0700461
Elliott Hughes814e4032011-08-23 12:07:56 -0700462TEST_F(JniInternalTest, BooleanArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700463 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
464 GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
Elliott Hughes814e4032011-08-23 12:07:56 -0700465}
466TEST_F(JniInternalTest, ByteArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700467 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
468 GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
Elliott Hughes814e4032011-08-23 12:07:56 -0700469}
470TEST_F(JniInternalTest, CharArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700471 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
472 GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
Elliott Hughes814e4032011-08-23 12:07:56 -0700473}
474TEST_F(JniInternalTest, DoubleArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700475 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
476 GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
Elliott Hughes814e4032011-08-23 12:07:56 -0700477}
478TEST_F(JniInternalTest, FloatArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700479 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
480 GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
Elliott Hughes814e4032011-08-23 12:07:56 -0700481}
482TEST_F(JniInternalTest, IntArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700483 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
484 GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
Elliott Hughes814e4032011-08-23 12:07:56 -0700485}
486TEST_F(JniInternalTest, LongArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700487 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
488 GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
Elliott Hughes814e4032011-08-23 12:07:56 -0700489}
490TEST_F(JniInternalTest, ShortArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700491 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
492 GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700493}
494
Elliott Hughesf2682d52011-08-15 16:37:04 -0700495TEST_F(JniInternalTest, NewObjectArray) {
Elliott Hughesbd935992011-08-22 11:59:34 -0700496 jclass element_class = env_->FindClass("java/lang/String");
Ian Rogers1d99e452014-01-02 17:36:41 -0800497 ASSERT_TRUE(element_class != nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700498 jclass array_class = env_->FindClass("[Ljava/lang/String;");
Ian Rogers1d99e452014-01-02 17:36:41 -0800499 ASSERT_TRUE(array_class != nullptr);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700500
Ian Rogers1d99e452014-01-02 17:36:41 -0800501 jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
502 EXPECT_TRUE(a != nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700503 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
504 EXPECT_EQ(0, env_->GetArrayLength(a));
505
Ian Rogers1d99e452014-01-02 17:36:41 -0800506 a = env_->NewObjectArray(1, element_class, nullptr);
507 EXPECT_TRUE(a != nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700508 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
509 EXPECT_EQ(1, env_->GetArrayLength(a));
Ian Rogers1d99e452014-01-02 17:36:41 -0800510 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
511}
512
513TEST_F(JniInternalTest, NewObjectArrayWithNegativeLength) {
514 jclass element_class = env_->FindClass("java/lang/String");
515 ASSERT_TRUE(element_class != nullptr);
516 jclass array_class = env_->FindClass("[Ljava/lang/String;");
517 ASSERT_TRUE(array_class != nullptr);
518 CheckJniAbortCatcher jni_abort_catcher;
519
520 env_->NewObjectArray(-1, element_class, nullptr);
521 jni_abort_catcher.Check("negative array length: -1");
522
523 env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr);
524 jni_abort_catcher.Check("negative array length: -2147483648");
525}
526
527TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) {
528 const char* primitive_descriptors = "VZBSCIJFD";
529 const char* primitive_names[] = {
530 "void", "boolean", "byte", "short", "char", "int", "long", "float", "double"
531 };
532 ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names));
533
534 CheckJniAbortCatcher jni_abort_catcher;
535 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
536 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
537 env_->NewObjectArray(1, primitive_class, nullptr);
538 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
539 jni_abort_catcher.Check(error_msg.c_str());
540 }
541}
542
543TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
544 jclass element_class = env_->FindClass("java/lang/String");
545 ASSERT_TRUE(element_class != nullptr);
546 jclass array_class = env_->FindClass("[Ljava/lang/String;");
547 ASSERT_TRUE(array_class != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -0700548
549 jstring s = env_->NewStringUTF("poop");
Ian Rogers1d99e452014-01-02 17:36:41 -0800550 jobjectArray a = env_->NewObjectArray(2, element_class, s);
551 EXPECT_TRUE(a != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -0700552 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
553 EXPECT_EQ(2, env_->GetArrayLength(a));
554 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
555 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
Ian Rogers1d99e452014-01-02 17:36:41 -0800556
557 // Attempt to incorrect create an array of strings with initial value of string arrays.
558 CheckJniAbortCatcher jni_abort_catcher;
559 env_->NewObjectArray(2, element_class, a);
560 jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element "
561 "type of 'java.lang.String'");
Elliott Hughesbd935992011-08-22 11:59:34 -0700562}
563
564TEST_F(JniInternalTest, GetArrayLength) {
565 // Already tested in NewObjectArray/NewPrimitiveArray.
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700566}
567
Elliott Hughes37f7a402011-08-22 18:56:01 -0700568TEST_F(JniInternalTest, GetObjectClass) {
569 jclass string_class = env_->FindClass("java/lang/String");
570 ASSERT_TRUE(string_class != NULL);
571 jclass class_class = env_->FindClass("java/lang/Class");
572 ASSERT_TRUE(class_class != NULL);
573
574 jstring s = env_->NewStringUTF("poop");
575 jclass c = env_->GetObjectClass(s);
576 ASSERT_TRUE(env_->IsSameObject(string_class, c));
577
578 jclass c2 = env_->GetObjectClass(c);
579 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
580}
581
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700582TEST_F(JniInternalTest, GetSuperclass) {
583 jclass object_class = env_->FindClass("java/lang/Object");
584 ASSERT_TRUE(object_class != NULL);
585 jclass string_class = env_->FindClass("java/lang/String");
586 ASSERT_TRUE(string_class != NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800587 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
588 ASSERT_TRUE(runnable_interface != NULL);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700589 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
590 ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800591 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700592}
593
Elliott Hughes37f7a402011-08-22 18:56:01 -0700594TEST_F(JniInternalTest, IsAssignableFrom) {
595 jclass object_class = env_->FindClass("java/lang/Object");
596 ASSERT_TRUE(object_class != NULL);
597 jclass string_class = env_->FindClass("java/lang/String");
598 ASSERT_TRUE(string_class != NULL);
599
600 ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
601 ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
602}
603
Elliott Hughesb465ab02011-08-24 11:21:21 -0700604TEST_F(JniInternalTest, GetObjectRefType) {
605 jclass local = env_->FindClass("java/lang/Object");
606 ASSERT_TRUE(local != NULL);
607 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
608
609 jobject global = env_->NewGlobalRef(local);
610 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
611
612 jweak weak_global = env_->NewWeakGlobalRef(local);
613 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
614
615 jobject invalid = reinterpret_cast<jobject>(this);
616 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
617
618 // TODO: invoke a native method and test that its arguments are considered local references.
619}
620
Mathieu Chartier08599992013-12-20 17:17:55 -0800621TEST_F(JniInternalTest, StaleWeakGlobal) {
622 jclass java_lang_Class = env_->FindClass("java/lang/Class");
623 ASSERT_TRUE(java_lang_Class != NULL);
624 jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, NULL);
625 ASSERT_TRUE(local_ref != NULL);
626 jweak weak_global = env_->NewWeakGlobalRef(local_ref);
627 ASSERT_TRUE(weak_global != NULL);
628 env_->DeleteLocalRef(local_ref);
629 Runtime::Current()->GetHeap()->CollectGarbage(false); // GC should clear the weak global.
630 jobject new_global_ref = env_->NewGlobalRef(weak_global);
631 EXPECT_TRUE(new_global_ref == NULL);
632 jobject new_local_ref = env_->NewLocalRef(weak_global);
633 EXPECT_TRUE(new_local_ref == NULL);
634}
635
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700636TEST_F(JniInternalTest, NewStringUTF) {
637 EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -0700638 jstring s;
639
640 s = env_->NewStringUTF("");
641 EXPECT_TRUE(s != NULL);
642 EXPECT_EQ(0, env_->GetStringLength(s));
643 EXPECT_EQ(0, env_->GetStringUTFLength(s));
644 s = env_->NewStringUTF("hello");
645 EXPECT_TRUE(s != NULL);
646 EXPECT_EQ(5, env_->GetStringLength(s));
647 EXPECT_EQ(5, env_->GetStringUTFLength(s));
648
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700649 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -0700650}
651
Elliott Hughes814e4032011-08-23 12:07:56 -0700652TEST_F(JniInternalTest, NewString) {
Elliott Hughes814e4032011-08-23 12:07:56 -0700653 jchar chars[] = { 'h', 'i' };
654 jstring s;
655 s = env_->NewString(chars, 0);
656 EXPECT_TRUE(s != NULL);
657 EXPECT_EQ(0, env_->GetStringLength(s));
658 EXPECT_EQ(0, env_->GetStringUTFLength(s));
659 s = env_->NewString(chars, 2);
660 EXPECT_TRUE(s != NULL);
661 EXPECT_EQ(2, env_->GetStringLength(s));
662 EXPECT_EQ(2, env_->GetStringUTFLength(s));
663
664 // TODO: check some non-ASCII strings.
665}
666
Jesse Wilson25e79a52011-11-18 15:31:58 -0500667TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
Ian Rogers1d99e452014-01-02 17:36:41 -0800668 jstring s = env_->NewString(nullptr, 0);
669 EXPECT_TRUE(s != nullptr);
Jesse Wilson25e79a52011-11-18 15:31:58 -0500670 EXPECT_EQ(0, env_->GetStringLength(s));
671}
672
Ian Rogers1d99e452014-01-02 17:36:41 -0800673TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) {
674 CheckJniAbortCatcher jni_abort_catcher;
675 env_->NewString(nullptr, 1);
676 jni_abort_catcher.Check("chars == null && char_count > 0");
677}
678
679TEST_F(JniInternalTest, NewStringNegativeLength) {
680 CheckJniAbortCatcher jni_abort_catcher;
681 env_->NewString(nullptr, -1);
682 jni_abort_catcher.Check("char_count < 0: -1");
683 env_->NewString(nullptr, std::numeric_limits<jint>::min());
684 jni_abort_catcher.Check("char_count < 0: -2147483648");
Jesse Wilson25e79a52011-11-18 15:31:58 -0500685}
686
Elliott Hughesb465ab02011-08-24 11:21:21 -0700687TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
688 // Already tested in the NewString/NewStringUTF tests.
689}
690
691TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
692 jstring s = env_->NewStringUTF("hello");
693 ASSERT_TRUE(s != NULL);
694
695 env_->GetStringRegion(s, -1, 0, NULL);
696 EXPECT_EXCEPTION(sioobe_);
697 env_->GetStringRegion(s, 0, -1, NULL);
698 EXPECT_EXCEPTION(sioobe_);
699 env_->GetStringRegion(s, 0, 10, NULL);
700 EXPECT_EXCEPTION(sioobe_);
701 env_->GetStringRegion(s, 10, 1, NULL);
702 EXPECT_EXCEPTION(sioobe_);
703
704 jchar chars[4] = { 'x', 'x', 'x', 'x' };
705 env_->GetStringRegion(s, 1, 2, &chars[1]);
706 EXPECT_EQ('x', chars[0]);
707 EXPECT_EQ('e', chars[1]);
708 EXPECT_EQ('l', chars[2]);
709 EXPECT_EQ('x', chars[3]);
710
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700711 // It's okay for the buffer to be NULL as long as the length is 0.
712 env_->GetStringRegion(s, 2, 0, NULL);
713 // Even if the offset is invalid...
714 env_->GetStringRegion(s, 123, 0, NULL);
715 EXPECT_EXCEPTION(sioobe_);
716
Elliott Hughesb465ab02011-08-24 11:21:21 -0700717 env_->GetStringUTFRegion(s, -1, 0, NULL);
718 EXPECT_EXCEPTION(sioobe_);
719 env_->GetStringUTFRegion(s, 0, -1, NULL);
720 EXPECT_EXCEPTION(sioobe_);
721 env_->GetStringUTFRegion(s, 0, 10, NULL);
722 EXPECT_EXCEPTION(sioobe_);
723 env_->GetStringUTFRegion(s, 10, 1, NULL);
724 EXPECT_EXCEPTION(sioobe_);
725
726 char bytes[4] = { 'x', 'x', 'x', 'x' };
727 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
728 EXPECT_EQ('x', bytes[0]);
729 EXPECT_EQ('e', bytes[1]);
730 EXPECT_EQ('l', bytes[2]);
731 EXPECT_EQ('x', bytes[3]);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700732
733 // It's okay for the buffer to be NULL as long as the length is 0.
734 env_->GetStringUTFRegion(s, 2, 0, NULL);
735 // Even if the offset is invalid...
736 env_->GetStringUTFRegion(s, 123, 0, NULL);
737 EXPECT_EXCEPTION(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -0700738}
739
Elliott Hughes75770752011-08-24 17:52:38 -0700740TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700741 // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
Elliott Hughesb264f082012-04-06 17:10:10 -0700742 {
Elliott Hughesb264f082012-04-06 17:10:10 -0700743 CheckJniAbortCatcher check_jni_abort_catcher;
744 EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
Elliott Hughes56ef0422012-06-19 14:35:04 -0700745 check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
Elliott Hughesb264f082012-04-06 17:10:10 -0700746 }
Elliott Hughes75770752011-08-24 17:52:38 -0700747
748 jstring s = env_->NewStringUTF("hello");
749 ASSERT_TRUE(s != NULL);
750
751 const char* utf = env_->GetStringUTFChars(s, NULL);
752 EXPECT_STREQ("hello", utf);
753 env_->ReleaseStringUTFChars(s, utf);
754
755 jboolean is_copy = JNI_FALSE;
756 utf = env_->GetStringUTFChars(s, &is_copy);
757 EXPECT_EQ(JNI_TRUE, is_copy);
758 EXPECT_STREQ("hello", utf);
759 env_->ReleaseStringUTFChars(s, utf);
760}
761
762TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
763 jstring s = env_->NewStringUTF("hello");
764 ASSERT_TRUE(s != NULL);
765
766 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
767 const jchar* chars = env_->GetStringChars(s, NULL);
768 EXPECT_EQ(expected[0], chars[0]);
769 EXPECT_EQ(expected[1], chars[1]);
770 EXPECT_EQ(expected[2], chars[2]);
771 EXPECT_EQ(expected[3], chars[3]);
772 EXPECT_EQ(expected[4], chars[4]);
773 env_->ReleaseStringChars(s, chars);
774
775 jboolean is_copy = JNI_FALSE;
776 chars = env_->GetStringChars(s, &is_copy);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700777 EXPECT_EQ(JNI_TRUE, is_copy);
Elliott Hughes75770752011-08-24 17:52:38 -0700778 EXPECT_EQ(expected[0], chars[0]);
779 EXPECT_EQ(expected[1], chars[1]);
780 EXPECT_EQ(expected[2], chars[2]);
781 EXPECT_EQ(expected[3], chars[3]);
782 EXPECT_EQ(expected[4], chars[4]);
783 env_->ReleaseStringChars(s, chars);
784}
785
786TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
787 jstring s = env_->NewStringUTF("hello");
788 ASSERT_TRUE(s != NULL);
789
790 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
791 const jchar* chars = env_->GetStringCritical(s, NULL);
792 EXPECT_EQ(expected[0], chars[0]);
793 EXPECT_EQ(expected[1], chars[1]);
794 EXPECT_EQ(expected[2], chars[2]);
795 EXPECT_EQ(expected[3], chars[3]);
796 EXPECT_EQ(expected[4], chars[4]);
797 env_->ReleaseStringCritical(s, chars);
798
799 jboolean is_copy = JNI_FALSE;
800 chars = env_->GetStringCritical(s, &is_copy);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700801 // TODO: Fix GetStringCritical to use the same mechanism as GetPrimitiveArrayElementsCritical.
802 EXPECT_EQ(JNI_TRUE, is_copy);
Elliott Hughes75770752011-08-24 17:52:38 -0700803 EXPECT_EQ(expected[0], chars[0]);
804 EXPECT_EQ(expected[1], chars[1]);
805 EXPECT_EQ(expected[2], chars[2]);
806 EXPECT_EQ(expected[3], chars[3]);
807 EXPECT_EQ(expected[4], chars[4]);
808 env_->ReleaseStringCritical(s, chars);
809}
810
Elliott Hughes814e4032011-08-23 12:07:56 -0700811TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
Elliott Hughesb264f082012-04-06 17:10:10 -0700812 jclass java_lang_Class = env_->FindClass("java/lang/Class");
813 ASSERT_TRUE(java_lang_Class != NULL);
Elliott Hughes289da822011-08-16 10:11:20 -0700814
Elliott Hughesb264f082012-04-06 17:10:10 -0700815 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL);
Elliott Hughes289da822011-08-16 10:11:20 -0700816 EXPECT_TRUE(array != NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -0700817 EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
Elliott Hughesb264f082012-04-06 17:10:10 -0700818 env_->SetObjectArrayElement(array, 0, java_lang_Class);
819 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700820
821 // ArrayIndexOutOfBounds for negative index.
Elliott Hughesb264f082012-04-06 17:10:10 -0700822 env_->SetObjectArrayElement(array, -1, java_lang_Class);
Elliott Hughes814e4032011-08-23 12:07:56 -0700823 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700824
825 // ArrayIndexOutOfBounds for too-large index.
Elliott Hughesb264f082012-04-06 17:10:10 -0700826 env_->SetObjectArrayElement(array, 1, java_lang_Class);
Elliott Hughes814e4032011-08-23 12:07:56 -0700827 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700828
Elliott Hughesb264f082012-04-06 17:10:10 -0700829 // ArrayStoreException thrown for bad types.
830 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
831 EXPECT_EXCEPTION(ase_);
Elliott Hughes289da822011-08-16 10:11:20 -0700832}
833
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700834#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
835 do { \
836 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
837 EXPECT_TRUE(fid != NULL); \
838 env_->SetStatic ## type ## Field(c, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -0800839 EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700840 env_->SetStatic ## type ## Field(c, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -0800841 EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700842 } while (false)
843
844#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
845 do { \
846 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
847 EXPECT_TRUE(fid != NULL); \
848 env_->Set ## type ## Field(instance, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -0800849 EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700850 env_->Set ## type ## Field(instance, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -0800851 EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700852 } while (false)
853
854
855TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800856 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700857 Thread::Current()->TransitionFromSuspendedToRunnable();
858 LoadDex("AllFields");
Brian Carlstrombd86bcc2013-03-10 20:26:16 -0700859 bool started = runtime_->Start();
860 CHECK(started);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700861
862 jclass c = env_->FindClass("AllFields");
863 ASSERT_TRUE(c != NULL);
864 jobject o = env_->AllocObject(c);
865 ASSERT_TRUE(o != NULL);
866
867 EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
868 EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
869 EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
870 EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
871 EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
872 EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
873 EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
874 EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
875
876 EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
877 EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
878 EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
879 EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
880 EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
881 EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
882 EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
883 EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
884}
885
886TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800887 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700888 Thread::Current()->TransitionFromSuspendedToRunnable();
889 LoadDex("AllFields");
Brian Carlstrom25c33252011-09-18 15:58:35 -0700890 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700891
892 jclass c = env_->FindClass("AllFields");
893 ASSERT_TRUE(c != NULL);
894 jobject o = env_->AllocObject(c);
895 ASSERT_TRUE(o != NULL);
896
897 jstring s1 = env_->NewStringUTF("hello");
898 ASSERT_TRUE(s1 != NULL);
899 jstring s2 = env_->NewStringUTF("world");
900 ASSERT_TRUE(s2 != NULL);
901
902 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
903 ASSERT_TRUE(s_fid != NULL);
904 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
905 ASSERT_TRUE(i_fid != NULL);
906
907 env_->SetStaticObjectField(c, s_fid, s1);
908 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
909 env_->SetStaticObjectField(c, s_fid, s2);
910 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
911
912 env_->SetObjectField(o, i_fid, s1);
913 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
914 env_->SetObjectField(o, i_fid, s2);
915 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
916}
917
Elliott Hughes18c07532011-08-18 15:50:51 -0700918TEST_F(JniInternalTest, NewLocalRef_NULL) {
919 EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
920}
921
922TEST_F(JniInternalTest, NewLocalRef) {
923 jstring s = env_->NewStringUTF("");
924 ASSERT_TRUE(s != NULL);
925 jobject o = env_->NewLocalRef(s);
926 EXPECT_TRUE(o != NULL);
927 EXPECT_TRUE(o != s);
928
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700929 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
Elliott Hughes18c07532011-08-18 15:50:51 -0700930}
931
932TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
933 env_->DeleteLocalRef(NULL);
934}
935
936TEST_F(JniInternalTest, DeleteLocalRef) {
937 jstring s = env_->NewStringUTF("");
938 ASSERT_TRUE(s != NULL);
939 env_->DeleteLocalRef(s);
940
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700941 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -0700942 {
Elliott Hughesb264f082012-04-06 17:10:10 -0700943 CheckJniAbortCatcher check_jni_abort_catcher;
944 env_->DeleteLocalRef(s);
Elliott Hughesa9137c62013-01-09 10:55:21 -0800945
Brian Carlstromea46f952013-07-30 01:26:50 -0700946 std::string expected(StringPrintf("native code passing in reference to "
947 "invalid local reference: %p", s));
Elliott Hughesa9137c62013-01-09 10:55:21 -0800948 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700949 }
Elliott Hughes18c07532011-08-18 15:50:51 -0700950
951 s = env_->NewStringUTF("");
952 ASSERT_TRUE(s != NULL);
953 jobject o = env_->NewLocalRef(s);
954 ASSERT_TRUE(o != NULL);
955
956 env_->DeleteLocalRef(s);
957 env_->DeleteLocalRef(o);
958}
959
Elliott Hughesaa836f72013-08-20 16:57:23 -0700960TEST_F(JniInternalTest, PushLocalFrame_10395422) {
961 // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
962 // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
963 // Android historically treated it, and it's how the RI treats it. It's also the more useful
964 // interpretation!
965 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
966 env_->PopLocalFrame(NULL);
967
968 // Negative capacities are not allowed.
969 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
970
971 // And it's okay to have an upper limit. Ours is currently 512.
972 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192));
973}
974
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700975TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
976 jobject original = env_->NewStringUTF("");
977 ASSERT_TRUE(original != NULL);
978
979 jobject outer;
980 jobject inner1, inner2;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700981 ScopedObjectAccess soa(env_);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800982 mirror::Object* inner2_direct_pointer;
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700983 {
Elliott Hughesaa836f72013-08-20 16:57:23 -0700984 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700985 outer = env_->NewLocalRef(original);
986
987 {
Elliott Hughesaa836f72013-08-20 16:57:23 -0700988 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700989 inner1 = env_->NewLocalRef(outer);
990 inner2 = env_->NewStringUTF("survivor");
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800991 inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2);
Elliott Hughes2ced6a52011-10-16 18:44:48 -0700992 env_->PopLocalFrame(inner2);
993 }
994
995 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
996 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
997 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
998
999 // Our local reference for the survivor is invalid because the survivor
1000 // gets a new local reference...
1001 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1002 // ...but the survivor should be in the local reference table.
Brian Carlstrom4d571432012-05-16 00:21:41 -07001003 JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(env_);
1004 EXPECT_TRUE(env->locals.ContainsDirectPointer(inner2_direct_pointer));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001005
1006 env_->PopLocalFrame(NULL);
1007 }
1008 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1009 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1010 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1011 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1012}
1013
Elliott Hughes18c07532011-08-18 15:50:51 -07001014TEST_F(JniInternalTest, NewGlobalRef_NULL) {
1015 EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
1016}
1017
1018TEST_F(JniInternalTest, NewGlobalRef) {
1019 jstring s = env_->NewStringUTF("");
1020 ASSERT_TRUE(s != NULL);
1021 jobject o = env_->NewGlobalRef(s);
1022 EXPECT_TRUE(o != NULL);
1023 EXPECT_TRUE(o != s);
1024
1025 // TODO: check that o is a global reference.
1026}
1027
1028TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
1029 env_->DeleteGlobalRef(NULL);
1030}
1031
1032TEST_F(JniInternalTest, DeleteGlobalRef) {
1033 jstring s = env_->NewStringUTF("");
1034 ASSERT_TRUE(s != NULL);
1035
1036 jobject o = env_->NewGlobalRef(s);
1037 ASSERT_TRUE(o != NULL);
1038 env_->DeleteGlobalRef(o);
1039
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001040 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001041 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001042 CheckJniAbortCatcher check_jni_abort_catcher;
1043 env_->DeleteGlobalRef(o);
Elliott Hughesa9137c62013-01-09 10:55:21 -08001044
Brian Carlstromea46f952013-07-30 01:26:50 -07001045 std::string expected(StringPrintf("native code passing in reference to "
1046 "invalid global reference: %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08001047 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -07001048 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001049
1050 jobject o1 = env_->NewGlobalRef(s);
1051 ASSERT_TRUE(o1 != NULL);
1052 jobject o2 = env_->NewGlobalRef(s);
1053 ASSERT_TRUE(o2 != NULL);
1054
1055 env_->DeleteGlobalRef(o1);
1056 env_->DeleteGlobalRef(o2);
1057}
1058
1059TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
1060 EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
1061}
1062
1063TEST_F(JniInternalTest, NewWeakGlobalRef) {
1064 jstring s = env_->NewStringUTF("");
1065 ASSERT_TRUE(s != NULL);
1066 jobject o = env_->NewWeakGlobalRef(s);
1067 EXPECT_TRUE(o != NULL);
1068 EXPECT_TRUE(o != s);
1069
1070 // TODO: check that o is a weak global reference.
1071}
1072
1073TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
1074 env_->DeleteWeakGlobalRef(NULL);
1075}
1076
1077TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1078 jstring s = env_->NewStringUTF("");
1079 ASSERT_TRUE(s != NULL);
1080
1081 jobject o = env_->NewWeakGlobalRef(s);
1082 ASSERT_TRUE(o != NULL);
1083 env_->DeleteWeakGlobalRef(o);
1084
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001085 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001086 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001087 CheckJniAbortCatcher check_jni_abort_catcher;
1088 env_->DeleteWeakGlobalRef(o);
Elliott Hughesa9137c62013-01-09 10:55:21 -08001089
Brian Carlstromea46f952013-07-30 01:26:50 -07001090 std::string expected(StringPrintf("native code passing in reference to "
1091 "invalid weak global reference: %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08001092 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -07001093 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001094
1095 jobject o1 = env_->NewWeakGlobalRef(s);
1096 ASSERT_TRUE(o1 != NULL);
1097 jobject o2 = env_->NewWeakGlobalRef(s);
1098 ASSERT_TRUE(o2 != NULL);
1099
1100 env_->DeleteWeakGlobalRef(o1);
1101 env_->DeleteWeakGlobalRef(o2);
1102}
1103
Elliott Hughes37f7a402011-08-22 18:56:01 -07001104TEST_F(JniInternalTest, Throw) {
1105 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1106
1107 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1108 ASSERT_TRUE(exception_class != NULL);
1109 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
1110 ASSERT_TRUE(exception != NULL);
1111
1112 EXPECT_EQ(JNI_OK, env_->Throw(exception));
1113 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughesa2501992011-08-26 19:39:54 -07001114 jthrowable thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001115 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001116 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001117}
1118
1119TEST_F(JniInternalTest, ThrowNew) {
1120 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1121
1122 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1123 ASSERT_TRUE(exception_class != NULL);
1124
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001125 jthrowable thrown_exception;
1126
Elliott Hughes37f7a402011-08-22 18:56:01 -07001127 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1128 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001129 thrown_exception = env_->ExceptionOccurred();
1130 env_->ExceptionClear();
1131 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1132
1133 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
1134 EXPECT_TRUE(env_->ExceptionCheck());
1135 thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001136 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001137 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001138}
1139
Ian Rogers1d99e452014-01-02 17:36:41 -08001140TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1141 // Start runtime.
1142 Thread* self = Thread::Current();
1143 self->TransitionFromSuspendedToRunnable();
1144 MakeExecutable(nullptr, "java.lang.Class");
1145 MakeExecutable(nullptr, "java.lang.Object");
1146 MakeExecutable(nullptr, "java.nio.DirectByteBuffer");
1147 MakeExecutable(nullptr, "java.nio.MemoryBlock");
1148 MakeExecutable(nullptr, "java.nio.MemoryBlock$UnmanagedBlock");
1149 MakeExecutable(nullptr, "java.nio.MappedByteBuffer");
1150 MakeExecutable(nullptr, "java.nio.ByteBuffer");
1151 MakeExecutable(nullptr, "java.nio.Buffer");
1152 // TODO: we only load a dex file here as starting the runtime relies upon it.
1153 const char* class_name = "StaticLeafMethods";
1154 LoadDex(class_name);
1155 bool started = runtime_->Start();
1156 ASSERT_TRUE(started);
1157
Elliott Hughesb465ab02011-08-24 11:21:21 -07001158 jclass buffer_class = env_->FindClass("java/nio/Buffer");
1159 ASSERT_TRUE(buffer_class != NULL);
1160
1161 char bytes[1024];
1162 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
1163 ASSERT_TRUE(buffer != NULL);
1164 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
1165 ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
1166 ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
1167}
1168
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001169TEST_F(JniInternalTest, MonitorEnterExit) {
1170 // Create an object to torture
1171 jclass object_class = env_->FindClass("java/lang/Object");
1172 ASSERT_TRUE(object_class != NULL);
1173 jobject object = env_->AllocObject(object_class);
1174 ASSERT_TRUE(object != NULL);
1175
1176 // Expected class of exceptions
1177 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
1178 ASSERT_TRUE(imse_class != NULL);
1179
1180 jthrowable thrown_exception;
1181
1182 // Unlock of unowned monitor
1183 env_->MonitorExit(object);
1184 EXPECT_TRUE(env_->ExceptionCheck());
1185 thrown_exception = env_->ExceptionOccurred();
1186 env_->ExceptionClear();
1187 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1188
1189 // Lock of unowned monitor
1190 env_->MonitorEnter(object);
1191 EXPECT_FALSE(env_->ExceptionCheck());
1192 // Regular unlock
1193 env_->MonitorExit(object);
1194 EXPECT_FALSE(env_->ExceptionCheck());
1195
1196 // Recursively lock a lot
1197 size_t max_recursive_lock = 1024;
1198 for (size_t i = 0; i < max_recursive_lock; i++) {
1199 env_->MonitorEnter(object);
1200 EXPECT_FALSE(env_->ExceptionCheck());
1201 }
1202 // Recursively unlock a lot
1203 for (size_t i = 0; i < max_recursive_lock; i++) {
1204 env_->MonitorExit(object);
1205 EXPECT_FALSE(env_->ExceptionCheck());
1206 }
1207
1208 // Unlock of unowned monitor
1209 env_->MonitorExit(object);
1210 EXPECT_TRUE(env_->ExceptionCheck());
1211 thrown_exception = env_->ExceptionOccurred();
1212 env_->ExceptionClear();
1213 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
Elliott Hughesa92853e2012-02-07 16:09:27 -08001214
1215 // It's an error to call MonitorEnter or MonitorExit on NULL.
Elliott Hughesb264f082012-04-06 17:10:10 -07001216 {
1217 CheckJniAbortCatcher check_jni_abort_catcher;
1218 env_->MonitorEnter(NULL);
1219 check_jni_abort_catcher.Check("in call to MonitorEnter");
Elliott Hughesb264f082012-04-06 17:10:10 -07001220
Elliott Hughesb264f082012-04-06 17:10:10 -07001221 env_->MonitorExit(NULL);
1222 check_jni_abort_catcher.Check("in call to MonitorExit");
1223 }
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001224}
1225
Brian Carlstrom4d571432012-05-16 00:21:41 -07001226TEST_F(JniInternalTest, DetachCurrentThread) {
1227 CleanUpJniEnv(); // cleanup now so TearDown won't have junk from wrong JNIEnv
1228 jint ok = vm_->DetachCurrentThread();
1229 EXPECT_EQ(JNI_OK, ok);
1230
1231 jint err = vm_->DetachCurrentThread();
1232 EXPECT_EQ(JNI_ERR, err);
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -08001233 vm_->AttachCurrentThread(&env_, NULL); // need attached thread for CommonRuntimeTest::TearDown
Brian Carlstrom4d571432012-05-16 00:21:41 -07001234}
1235
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001236} // namespace art