2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "reflection.h"
21 #include "ScopedLocalRef.h"
23 #include "art_method-inl.h"
24 #include "base/enums.h"
25 #include "common_compiler_test.h"
26 #include "jni_internal.h"
27 #include "scoped_thread_state_change-inl.h"
31 // TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used.
32 class ReflectionTest : public CommonCompilerTest {
34 virtual void SetUp() {
35 CommonCompilerTest::SetUp();
37 vm_ = Runtime::Current()->GetJavaVM();
39 // Turn on -verbose:jni for the JNI tests.
40 // gLogVerbosity.jni = true;
42 vm_->AttachCurrentThread(&env_, nullptr);
44 ScopedLocalRef<jclass> aioobe(env_,
45 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
46 CHECK(aioobe.get() != nullptr);
47 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
49 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
50 CHECK(ase.get() != nullptr);
51 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
53 ScopedLocalRef<jclass> sioobe(env_,
54 env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
55 CHECK(sioobe.get() != nullptr);
56 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
59 void CleanUpJniEnv() {
60 if (aioobe_ != nullptr) {
61 env_->DeleteGlobalRef(aioobe_);
64 if (ase_ != nullptr) {
65 env_->DeleteGlobalRef(ase_);
68 if (sioobe_ != nullptr) {
69 env_->DeleteGlobalRef(sioobe_);
74 virtual void TearDown() {
76 CommonCompilerTest::TearDown();
79 jclass GetPrimitiveClass(char descriptor) {
80 ScopedObjectAccess soa(env_);
81 mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
83 return soa.AddLocalReference<jclass>(c);
86 void ReflectionTestMakeExecutable(ArtMethod** method,
87 ObjPtr<mirror::Object>* receiver,
89 const char* method_name,
90 const char* method_signature)
91 REQUIRES_SHARED(Locks::mutator_lock_) {
92 const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
93 jobject jclass_loader(LoadDex(class_name));
94 Thread* self = Thread::Current();
95 StackHandleScope<3> hs(self);
96 Handle<mirror::ClassLoader> class_loader(
98 ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader>(jclass_loader)));
100 MakeExecutable(nullptr, "java.lang.Class");
101 MakeExecutable(nullptr, "java.lang.Object");
103 MakeExecutable(class_loader.Get(), class_name);
105 ObjPtr<mirror::Class> c = class_linker_->FindClass(self,
106 DotToDescriptor(class_name).c_str(),
110 *method = is_static ? c->FindDirectMethod(method_name, method_signature, kRuntimePointerSize)
111 : c->FindVirtualMethod(method_name, method_signature, kRuntimePointerSize);
112 CHECK(method != nullptr);
117 // Ensure class is initialized before allocating object
119 StackHandleScope<1> hs2(self);
120 HandleWrapperObjPtr<mirror::Class> h_class(hs2.NewHandleWrapper(&c));
121 bool initialized = class_linker_->EnsureInitialized(self, h_class, true, true);
124 *receiver = c->AllocObject(self);
128 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(receiver));
129 bool started = runtime_->Start();
131 self->TransitionFromSuspendedToRunnable();
134 void InvokeNopMethod(bool is_static) {
135 ScopedObjectAccess soa(env_);
137 ObjPtr<mirror::Object> receiver;
138 ReflectionTestMakeExecutable(&method, &receiver, is_static, "nop", "()V");
139 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
140 InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), nullptr);
143 void InvokeIdentityByteMethod(bool is_static) {
144 ScopedObjectAccess soa(env_);
146 ObjPtr<mirror::Object> receiver;
147 ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(B)B");
148 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
152 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
153 EXPECT_EQ(0, result.GetB());
156 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
157 EXPECT_EQ(-1, result.GetB());
159 args[0].b = SCHAR_MAX;
160 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
161 EXPECT_EQ(SCHAR_MAX, result.GetB());
163 static_assert(SCHAR_MIN == -128, "SCHAR_MIN unexpected");
164 args[0].b = SCHAR_MIN;
165 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
166 EXPECT_EQ(SCHAR_MIN, result.GetB());
169 void InvokeIdentityIntMethod(bool is_static) {
170 ScopedObjectAccess soa(env_);
172 ObjPtr<mirror::Object> receiver;
173 ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(I)I");
174 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
178 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
179 EXPECT_EQ(0, result.GetI());
182 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
183 EXPECT_EQ(-1, result.GetI());
186 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
187 EXPECT_EQ(INT_MAX, result.GetI());
190 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
191 EXPECT_EQ(INT_MIN, result.GetI());
194 void InvokeIdentityDoubleMethod(bool is_static) {
195 ScopedObjectAccess soa(env_);
197 ObjPtr<mirror::Object> receiver;
198 ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(D)D");
199 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
203 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
204 EXPECT_DOUBLE_EQ(0.0, result.GetD());
207 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
208 EXPECT_DOUBLE_EQ(-1.0, result.GetD());
211 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
212 EXPECT_DOUBLE_EQ(DBL_MAX, result.GetD());
215 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
216 EXPECT_DOUBLE_EQ(DBL_MIN, result.GetD());
219 void InvokeSumIntIntMethod(bool is_static) {
220 ScopedObjectAccess soa(env_);
222 ObjPtr<mirror::Object> receiver;
223 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(II)I");
224 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
229 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
230 EXPECT_EQ(3, result.GetI());
234 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
235 EXPECT_EQ(3, result.GetI());
239 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
240 EXPECT_EQ(-1, result.GetI());
244 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
245 EXPECT_EQ(-2, result.GetI());
248 void InvokeSumIntIntIntMethod(bool is_static) {
249 ScopedObjectAccess soa(env_);
251 ObjPtr<mirror::Object> receiver;
252 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(III)I");
253 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
259 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
260 EXPECT_EQ(0, result.GetI());
265 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
266 EXPECT_EQ(6, result.GetI());
271 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
272 EXPECT_EQ(-2, result.GetI());
277 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
278 EXPECT_EQ(2147483646, result.GetI());
283 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
284 EXPECT_EQ(2147483645, result.GetI());
287 void InvokeSumIntIntIntIntMethod(bool is_static) {
288 ScopedObjectAccess soa(env_);
290 ObjPtr<mirror::Object> receiver;
291 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIII)I");
292 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
299 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
300 EXPECT_EQ(0, result.GetI());
306 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
307 EXPECT_EQ(10, result.GetI());
313 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
314 EXPECT_EQ(2, result.GetI());
320 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
321 EXPECT_EQ(-2, result.GetI());
327 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
328 EXPECT_EQ(-4, result.GetI());
331 void InvokeSumIntIntIntIntIntMethod(bool is_static) {
332 ScopedObjectAccess soa(env_);
334 ObjPtr<mirror::Object> receiver;
335 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIIII)I");
336 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
344 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
345 EXPECT_EQ(0, result.GetI());
352 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
353 EXPECT_EQ(15, result.GetI());
360 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
361 EXPECT_EQ(-3, result.GetI());
368 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
369 EXPECT_EQ(2147483645, result.GetI());
376 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
377 EXPECT_EQ(2147483643, result.GetI());
380 void InvokeSumDoubleDoubleMethod(bool is_static) {
381 ScopedObjectAccess soa(env_);
383 ObjPtr<mirror::Object> receiver;
384 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DD)D");
385 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
390 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
391 EXPECT_DOUBLE_EQ(0.0, result.GetD());
395 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
396 EXPECT_DOUBLE_EQ(3.0, result.GetD());
400 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
401 EXPECT_DOUBLE_EQ(-1.0, result.GetD());
405 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
406 EXPECT_DOUBLE_EQ(1.7976931348623157e308, result.GetD());
410 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
411 EXPECT_DOUBLE_EQ(INFINITY, result.GetD());
414 void InvokeSumDoubleDoubleDoubleMethod(bool is_static) {
415 ScopedObjectAccess soa(env_);
417 ObjPtr<mirror::Object> receiver;
418 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDD)D");
419 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
425 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
426 EXPECT_DOUBLE_EQ(0.0, result.GetD());
431 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
432 EXPECT_DOUBLE_EQ(6.0, result.GetD());
437 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
438 EXPECT_DOUBLE_EQ(2.0, result.GetD());
441 void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static) {
442 ScopedObjectAccess soa(env_);
444 ObjPtr<mirror::Object> receiver;
445 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDD)D");
446 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
453 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
454 EXPECT_DOUBLE_EQ(0.0, result.GetD());
460 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
461 EXPECT_DOUBLE_EQ(10.0, result.GetD());
467 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
468 EXPECT_DOUBLE_EQ(-2.0, result.GetD());
471 void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static) {
472 ScopedObjectAccess soa(env_);
474 ObjPtr<mirror::Object> receiver;
475 ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDDD)D");
476 ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
484 JValue result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
485 EXPECT_DOUBLE_EQ(0.0, result.GetD());
492 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
493 EXPECT_DOUBLE_EQ(15.0, result.GetD());
500 result = InvokeWithJValues(soa, receiver_ref.get(), jni::EncodeArtMethod(method), args);
501 EXPECT_DOUBLE_EQ(3.0, result.GetD());
511 TEST_F(ReflectionTest, StaticMainMethod) {
512 ScopedObjectAccess soa(Thread::Current());
513 jobject jclass_loader = LoadDex("Main");
514 StackHandleScope<1> hs(soa.Self());
515 Handle<mirror::ClassLoader> class_loader(
516 hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
517 CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
519 mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
520 ASSERT_TRUE(klass != nullptr);
522 ArtMethod* method = klass->FindDirectMethod("main",
523 "([Ljava/lang/String;)V",
524 kRuntimePointerSize);
525 ASSERT_TRUE(method != nullptr);
528 bool started = runtime_->Start();
530 soa.Self()->TransitionFromSuspendedToRunnable();
534 InvokeWithJValues(soa, nullptr, jni::EncodeArtMethod(method), args);
537 TEST_F(ReflectionTest, StaticNopMethod) {
538 InvokeNopMethod(true);
541 TEST_F(ReflectionTest, NonStaticNopMethod) {
542 InvokeNopMethod(false);
545 TEST_F(ReflectionTest, StaticIdentityByteMethod) {
546 InvokeIdentityByteMethod(true);
549 TEST_F(ReflectionTest, NonStaticIdentityByteMethod) {
550 InvokeIdentityByteMethod(false);
553 TEST_F(ReflectionTest, StaticIdentityIntMethod) {
554 InvokeIdentityIntMethod(true);
557 TEST_F(ReflectionTest, NonStaticIdentityIntMethod) {
558 InvokeIdentityIntMethod(false);
561 TEST_F(ReflectionTest, StaticIdentityDoubleMethod) {
562 InvokeIdentityDoubleMethod(true);
565 TEST_F(ReflectionTest, NonStaticIdentityDoubleMethod) {
566 InvokeIdentityDoubleMethod(false);
569 TEST_F(ReflectionTest, StaticSumIntIntMethod) {
570 InvokeSumIntIntMethod(true);
573 TEST_F(ReflectionTest, NonStaticSumIntIntMethod) {
574 InvokeSumIntIntMethod(false);
577 TEST_F(ReflectionTest, StaticSumIntIntIntMethod) {
578 InvokeSumIntIntIntMethod(true);
581 TEST_F(ReflectionTest, NonStaticSumIntIntIntMethod) {
582 InvokeSumIntIntIntMethod(false);
585 TEST_F(ReflectionTest, StaticSumIntIntIntIntMethod) {
586 InvokeSumIntIntIntIntMethod(true);
589 TEST_F(ReflectionTest, NonStaticSumIntIntIntIntMethod) {
590 InvokeSumIntIntIntIntMethod(false);
593 TEST_F(ReflectionTest, StaticSumIntIntIntIntIntMethod) {
594 InvokeSumIntIntIntIntIntMethod(true);
597 TEST_F(ReflectionTest, NonStaticSumIntIntIntIntIntMethod) {
598 InvokeSumIntIntIntIntIntMethod(false);
601 TEST_F(ReflectionTest, StaticSumDoubleDoubleMethod) {
602 InvokeSumDoubleDoubleMethod(true);
605 TEST_F(ReflectionTest, NonStaticSumDoubleDoubleMethod) {
606 InvokeSumDoubleDoubleMethod(false);
609 TEST_F(ReflectionTest, StaticSumDoubleDoubleDoubleMethod) {
610 InvokeSumDoubleDoubleDoubleMethod(true);
613 TEST_F(ReflectionTest, NonStaticSumDoubleDoubleDoubleMethod) {
614 InvokeSumDoubleDoubleDoubleMethod(false);
617 TEST_F(ReflectionTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
618 InvokeSumDoubleDoubleDoubleDoubleMethod(true);
621 TEST_F(ReflectionTest, NonStaticSumDoubleDoubleDoubleDoubleMethod) {
622 InvokeSumDoubleDoubleDoubleDoubleMethod(false);
625 TEST_F(ReflectionTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
626 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(true);
629 TEST_F(ReflectionTest, NonStaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
630 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(false);