diff options
-rw-r--r-- | runtime/debugger.cc | 3 | ||||
-rw-r--r-- | runtime/indirect_reference_table-inl.h | 9 | ||||
-rw-r--r-- | runtime/indirect_reference_table.h | 11 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 49 | ||||
-rw-r--r-- | runtime/jni_internal_test.cc | 3 | ||||
-rw-r--r-- | runtime/reflection.cc | 47 | ||||
-rw-r--r-- | runtime/reflection.h | 6 | ||||
-rw-r--r-- | runtime/reflection_test.cc | 104 | ||||
-rw-r--r-- | runtime/thread.cc | 6 | ||||
-rw-r--r-- | test/004-JniTest/jni_test.cc | 63 | ||||
-rw-r--r-- | test/020-string/src/Main.java | 36 |
11 files changed, 238 insertions, 99 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 852ba49cd2..0eb7f2b855 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -3974,7 +3974,8 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { CHECK_EQ(sizeof(jvalue), sizeof(uint64_t)); - JValue result = InvokeWithJValues(soa, pReq->receiver.Read(), soa.EncodeMethod(m.Get()), + ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(pReq->receiver.Read())); + JValue result = InvokeWithJValues(soa, ref.get(), soa.EncodeMethod(m.Get()), reinterpret_cast<jvalue*>(pReq->arg_values)); pReq->result_tag = BasicTagFromDescriptor(m.Get()->GetShorty()); diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h index 639be515f6..39d850fc4d 100644 --- a/runtime/indirect_reference_table-inl.h +++ b/runtime/indirect_reference_table-inl.h @@ -82,6 +82,15 @@ inline mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const { return obj; } +inline void IndirectReferenceTable::Update(IndirectRef iref, mirror::Object* obj) { + if (!GetChecked(iref)) { + LOG(WARNING) << "IndirectReferenceTable Update failed to find reference " << iref; + return; + } + uint32_t idx = ExtractIndex(iref); + table_[idx].SetReference(obj); +} + } // namespace art #endif // ART_RUNTIME_INDIRECT_REFERENCE_TABLE_INL_H_ diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index a0e53af181..dea5dfdf90 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -213,6 +213,10 @@ class IrtEntry { uint32_t GetSerial() const { return serial_; } + void SetReference(mirror::Object* obj) { + DCHECK_LT(serial_, kIRTPrevCount); + references_[serial_] = GcRoot<mirror::Object>(obj); + } private: uint32_t serial_; @@ -294,6 +298,13 @@ class IndirectReferenceTable { } /* + * Update an existing entry. + * + * Updates an existing indirect reference to point to a new object. + */ + void Update(IndirectRef iref, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + /* * Remove an existing entry. * * If the entry is not between the current top index and the bottom index diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index fd386d7b38..33884151a1 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -682,8 +682,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(obj); CHECK_NON_NULL_ARGUMENT(mid); ScopedObjectAccess soa(env); - JValue result(InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args)); + JValue result(InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args)); return soa.AddLocalReference<jobject>(result.GetL()); } @@ -709,8 +708,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetZ(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetZ(); } static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -735,8 +733,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetB(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetB(); } static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -761,8 +758,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetC(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetC(); } static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -787,8 +783,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetD(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetD(); } static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -813,8 +808,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetF(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetF(); } static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -839,8 +833,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetI(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetI(); } static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -865,8 +858,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetJ(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetJ(); } static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -891,8 +883,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, - args).GetS(); + return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetS(); } static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -916,7 +907,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); - InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); + InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args); } static jobject CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -945,7 +936,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(obj); CHECK_NON_NULL_ARGUMENT(mid); ScopedObjectAccess soa(env); - JValue result(InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args)); + JValue result(InvokeWithJValues(soa, obj, mid, args)); return soa.AddLocalReference<jobject>(result.GetL()); } @@ -974,7 +965,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ(); + return InvokeWithJValues(soa, obj, mid, args).GetZ(); } static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1001,7 +992,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB(); + return InvokeWithJValues(soa, obj, mid, args).GetB(); } static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1028,7 +1019,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC(); + return InvokeWithJValues(soa, obj, mid, args).GetC(); } static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1055,7 +1046,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS(); + return InvokeWithJValues(soa, obj, mid, args).GetS(); } static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1082,7 +1073,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI(); + return InvokeWithJValues(soa, obj, mid, args).GetI(); } static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1109,7 +1100,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ(); + return InvokeWithJValues(soa, obj, mid, args).GetJ(); } static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1136,7 +1127,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF(); + return InvokeWithJValues(soa, obj, mid, args).GetF(); } static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1163,7 +1154,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD(); + return InvokeWithJValues(soa, obj, mid, args).GetD(); } static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1189,7 +1180,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); - InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); + InvokeWithJValues(soa, obj, mid, args); } static jfieldID GetFieldID(JNIEnv* env, jclass java_class, const char* name, const char* sig) { diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 3d14a4e284..581ef0e61a 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -858,8 +858,7 @@ TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) { jstring s = reinterpret_cast<jstring>(env_->AllocObject(c)); ASSERT_NE(s, nullptr); env_->CallVoidMethod(s, mid2); - // With the string change, this should now throw an UnsupportedOperationException. - ASSERT_EQ(JNI_TRUE, env_->ExceptionCheck()); + ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck()); env_->ExceptionClear(); mid = env_->GetMethodID(c, "length", "()I"); diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 49e1b8edf6..d321d272ea 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -21,6 +21,7 @@ #include "common_throws.h" #include "dex_file-inl.h" #include "entrypoints/entrypoint_utils.h" +#include "indirect_reference_table-inl.h" #include "jni_internal.h" #include "mirror/abstract_method.h" #include "mirror/art_method-inl.h" @@ -449,6 +450,11 @@ JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject o } mirror::ArtMethod* method = soa.DecodeMethod(mid); + bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); + if (is_string_init) { + // Replace calls to String.<init> with equivalent StringFactory call. + method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); + } mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); uint32_t shorty_len = 0; const char* shorty = method->GetShorty(&shorty_len); @@ -456,11 +462,15 @@ JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject o ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); InvokeWithArgArray(soa, method, &arg_array, &result, shorty); + if (is_string_init) { + // For string init, remap original receiver to StringFactory result. + soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL()); + } return result; } -JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver, - jmethodID mid, jvalue* args) { +JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, + jvalue* args) { // We want to make sure that the stack is not within a small distance from the // protected region in case we are calling into a leaf function whose stack // check has been elided. @@ -470,17 +480,27 @@ JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::O } mirror::ArtMethod* method = soa.DecodeMethod(mid); + bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); + if (is_string_init) { + // Replace calls to String.<init> with equivalent StringFactory call. + method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); + } + mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); uint32_t shorty_len = 0; const char* shorty = method->GetShorty(&shorty_len); JValue result; ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromJValues(soa, receiver, args); InvokeWithArgArray(soa, method, &arg_array, &result, shorty); + if (is_string_init) { + // For string init, remap original receiver to StringFactory result. + soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL()); + } return result; } JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, - mirror::Object* receiver, jmethodID mid, jvalue* args) { + jobject obj, jmethodID mid, jvalue* args) { // We want to make sure that the stack is not within a small distance from the // protected region in case we are calling into a leaf function whose stack // check has been elided. @@ -489,13 +509,24 @@ JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnab return JValue(); } + mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); + bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); + if (is_string_init) { + // Replace calls to String.<init> with equivalent StringFactory call. + method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); + receiver = nullptr; + } uint32_t shorty_len = 0; const char* shorty = method->GetShorty(&shorty_len); JValue result; ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromJValues(soa, receiver, args); InvokeWithArgArray(soa, method, &arg_array, &result, shorty); + if (is_string_init) { + // For string init, remap original receiver to StringFactory result. + soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL()); + } return result; } @@ -511,12 +542,22 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnab mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); + bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); + if (is_string_init) { + // Replace calls to String.<init> with equivalent StringFactory call. + method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); + receiver = nullptr; + } uint32_t shorty_len = 0; const char* shorty = method->GetShorty(&shorty_len); JValue result; ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); InvokeWithArgArray(soa, method, &arg_array, &result, shorty); + if (is_string_init) { + // For string init, remap original receiver to StringFactory result. + soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL()); + } return result; } diff --git a/runtime/reflection.h b/runtime/reflection.h index 37f8a6af55..6b5ffc72f2 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -49,12 +49,12 @@ JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject o va_list args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver, - jmethodID mid, jvalue* args) +JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, + jvalue* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, - mirror::Object* receiver, jmethodID mid, jvalue* args) + jobject obj, jmethodID mid, jvalue* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc index a62bc5ea62..36e444a061 100644 --- a/runtime/reflection_test.cc +++ b/runtime/reflection_test.cc @@ -133,7 +133,8 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "nop", "()V"); - InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), nullptr); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); + InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), nullptr); } void InvokeIdentityByteMethod(bool is_static) { @@ -141,22 +142,23 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(B)B"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[1]; args[0].b = 0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(0, result.GetB()); args[0].b = -1; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-1, result.GetB()); args[0].b = SCHAR_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(SCHAR_MAX, result.GetB()); args[0].b = (SCHAR_MIN << 24) >> 24; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(SCHAR_MIN, result.GetB()); } @@ -165,22 +167,23 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(I)I"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[1]; args[0].i = 0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(0, result.GetI()); args[0].i = -1; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-1, result.GetI()); args[0].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(INT_MAX, result.GetI()); args[0].i = INT_MIN; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(INT_MIN, result.GetI()); } @@ -189,22 +192,23 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(D)D"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[1]; args[0].d = 0.0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(0.0, result.GetD()); args[0].d = -1.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(-1.0, result.GetD()); args[0].d = DBL_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(DBL_MAX, result.GetD()); args[0].d = DBL_MIN; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(DBL_MIN, result.GetD()); } @@ -213,26 +217,27 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(II)I"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[2]; args[0].i = 1; args[1].i = 2; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(3, result.GetI()); args[0].i = -2; args[1].i = 5; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(3, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MIN; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-1, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-2, result.GetI()); } @@ -241,36 +246,37 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(III)I"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[3]; args[0].i = 0; args[1].i = 0; args[2].i = 0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(0, result.GetI()); args[0].i = 1; args[1].i = 2; args[2].i = 3; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(6, result.GetI()); args[0].i = -1; args[1].i = 2; args[2].i = -3; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-2, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MIN; args[2].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(2147483646, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MAX; args[2].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(2147483645, result.GetI()); } @@ -279,41 +285,42 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIII)I"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[4]; args[0].i = 0; args[1].i = 0; args[2].i = 0; args[3].i = 0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(0, result.GetI()); args[0].i = 1; args[1].i = 2; args[2].i = 3; args[3].i = 4; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(10, result.GetI()); args[0].i = -1; args[1].i = 2; args[2].i = -3; args[3].i = 4; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(2, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MIN; args[2].i = INT_MAX; args[3].i = INT_MIN; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-2, result.GetI()); args[0].i = INT_MAX; args[1].i = INT_MAX; args[2].i = INT_MAX; args[3].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-4, result.GetI()); } @@ -322,6 +329,7 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIIII)I"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[5]; args[0].i = 0; @@ -329,7 +337,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].i = 0; args[3].i = 0; args[4].i = 0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(0, result.GetI()); args[0].i = 1; @@ -337,7 +345,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].i = 3; args[3].i = 4; args[4].i = 5; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(15, result.GetI()); args[0].i = -1; @@ -345,7 +353,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].i = -3; args[3].i = 4; args[4].i = -5; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(-3, result.GetI()); args[0].i = INT_MAX; @@ -353,7 +361,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].i = INT_MAX; args[3].i = INT_MIN; args[4].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(2147483645, result.GetI()); args[0].i = INT_MAX; @@ -361,7 +369,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].i = INT_MAX; args[3].i = INT_MAX; args[4].i = INT_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_EQ(2147483643, result.GetI()); } @@ -370,31 +378,32 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DD)D"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[2]; args[0].d = 0.0; args[1].d = 0.0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(0.0, result.GetD()); args[0].d = 1.0; args[1].d = 2.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(3.0, result.GetD()); args[0].d = 1.0; args[1].d = -2.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(-1.0, result.GetD()); args[0].d = DBL_MAX; args[1].d = DBL_MIN; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(1.7976931348623157e308, result.GetD()); args[0].d = DBL_MAX; args[1].d = DBL_MAX; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(INFINITY, result.GetD()); } @@ -403,24 +412,25 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDD)D"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[3]; args[0].d = 0.0; args[1].d = 0.0; args[2].d = 0.0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(0.0, result.GetD()); args[0].d = 1.0; args[1].d = 2.0; args[2].d = 3.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(6.0, result.GetD()); args[0].d = 1.0; args[1].d = -2.0; args[2].d = 3.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(2.0, result.GetD()); } @@ -429,27 +439,28 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDD)D"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[4]; args[0].d = 0.0; args[1].d = 0.0; args[2].d = 0.0; args[3].d = 0.0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(0.0, result.GetD()); args[0].d = 1.0; args[1].d = 2.0; args[2].d = 3.0; args[3].d = 4.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(10.0, result.GetD()); args[0].d = 1.0; args[1].d = -2.0; args[2].d = 3.0; args[3].d = -4.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(-2.0, result.GetD()); } @@ -458,6 +469,7 @@ class ReflectionTest : public CommonCompilerTest { mirror::ArtMethod* method; mirror::Object* receiver; ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDDD)D"); + ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); jvalue args[5]; args[0].d = 0.0; @@ -465,7 +477,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].d = 0.0; args[3].d = 0.0; args[4].d = 0.0; - JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + JValue result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(0.0, result.GetD()); args[0].d = 1.0; @@ -473,7 +485,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].d = 3.0; args[3].d = 4.0; args[4].d = 5.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(15.0, result.GetD()); args[0].d = 1.0; @@ -481,7 +493,7 @@ class ReflectionTest : public CommonCompilerTest { args[2].d = 3.0; args[3].d = -4.0; args[4].d = 5.0; - result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args); + result = InvokeWithJValues(soa, receiver_ref.get(), soa.EncodeMethod(method), args); EXPECT_DOUBLE_EQ(3.0, result.GetD()); } diff --git a/runtime/thread.cc b/runtime/thread.cc index 148bb6d7d7..2145c9c963 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -216,7 +216,8 @@ void* Thread::CreateCallback(void* arg) { // Invoke the 'run' method of our java.lang.Thread. mirror::Object* receiver = self->tlsPtr_.opeer; jmethodID mid = WellKnownClasses::java_lang_Thread_run; - InvokeVirtualOrInterfaceWithJValues(soa, receiver, mid, nullptr); + ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(receiver)); + InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr); } // Detach and delete self. Runtime::Current()->GetThreadList()->Unregister(self); @@ -1886,7 +1887,8 @@ void Thread::ThrowNewWrappedException(const char* exception_class_descriptor, jv_args[i].l = cause.get(); ++i; } - InvokeWithJValues(soa, exception.Get(), soa.EncodeMethod(exception_init_method), jv_args); + ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(exception.Get())); + InvokeWithJValues(soa, ref.get(), soa.EncodeMethod(exception_init_method), jv_args); if (LIKELY(!IsExceptionPending())) { SetException(exception.Get()); } diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc index cdc546155d..1ec0cf2d43 100644 --- a/test/004-JniTest/jni_test.cc +++ b/test/004-JniTest/jni_test.cc @@ -550,21 +550,58 @@ extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) { } extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) { - const char* string = "Test"; - int length = strlen(string); jclass c = env->FindClass("java/lang/String"); - assert(c != NULL); - jmethodID method = env->GetMethodID(c, "<init>", "([B)V"); - assert(method != NULL); + assert(c != nullptr); + + jmethodID mid1 = env->GetMethodID(c, "<init>", "()V"); + assert(mid1 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V"); + assert(mid2 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V"); + assert(mid3 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V"); + assert(mid4 != nullptr); assert(!env->ExceptionCheck()); - jbyteArray array = env->NewByteArray(length); - env->SetByteArrayRegion(array, 0, length, reinterpret_cast<const jbyte*>(string)); - jobject o = env->NewObject(c, method, array); - assert(o != NULL); - jstring s = reinterpret_cast<jstring>(o); - assert(env->GetStringLength(s) == length); - assert(env->GetStringUTFLength(s) == length); + + const char* test_array = "Test"; + int byte_array_length = strlen(test_array); + jbyteArray byte_array = env->NewByteArray(byte_array_length); + env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array)); + + // Test NewObject + jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array)); + assert(s != nullptr); + assert(env->GetStringLength(s) == byte_array_length); + assert(env->GetStringUTFLength(s) == byte_array_length); const char* chars = env->GetStringUTFChars(s, nullptr); - assert(strcmp(string, chars) == 0); + assert(strcmp(test_array, chars) == 0); env->ReleaseStringUTFChars(s, chars); + + // Test AllocObject and Call(Nonvirtual)VoidMethod + jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s1 != nullptr); + jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s2 != nullptr); + jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s3 != nullptr); + jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s4 != nullptr); + + jcharArray char_array = env->NewCharArray(5); + jstring string_arg = env->NewStringUTF("helloworld"); + + // With Var Args + env->CallVoidMethod(s1, mid1); + env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array); + + // With JValues + jvalue args3[1]; + args3[0].l = char_array; + jvalue args4[1]; + args4[0].l = string_arg; + env->CallVoidMethodA(s3, mid3, args3); + env->CallNonvirtualVoidMethodA(s4, c, mid4, args4); } diff --git a/test/020-string/src/Main.java b/test/020-string/src/Main.java index bb8ce1fa51..b876e6ad21 100644 --- a/test/020-string/src/Main.java +++ b/test/020-string/src/Main.java @@ -14,6 +14,9 @@ * limitations under the License. */ +import java.nio.charset.Charset; +import java.io.UnsupportedEncodingException; + /** * Simple string test. */ @@ -21,6 +24,7 @@ public class Main { public static void main(String args[]) { basicTest(); indexTest(); + constructorTest(); } public static void basicTest() { @@ -81,4 +85,36 @@ public class Main { subStr.indexOf('&') + ":" + baseStr.indexOf(0x12341234)); } + + public static void constructorTest() { + byte[] byteArray = "byteArray".getBytes(); + char[] charArray = new char[] { 'c', 'h', 'a', 'r', 'A', 'r', 'r', 'a', 'y' }; + String charsetName = "US-ASCII"; + Charset charset = Charset.forName("UTF-8"); + String string = "string"; + StringBuffer stringBuffer = new StringBuffer("stringBuffer"); + int [] codePoints = new int[] { 65, 66, 67, 68, 69 }; + StringBuilder stringBuilder = new StringBuilder("stringBuilder"); + + String s1 = new String(); + String s2 = new String(byteArray); + String s3 = new String(byteArray, 1); + String s4 = new String(byteArray, 0, 4); + String s5 = new String(byteArray, 2, 4, 5); + + try { + String s6 = new String(byteArray, 2, 4, charsetName); + String s7 = new String(byteArray, charsetName); + } catch (UnsupportedEncodingException e) { + System.out.println("Got unexpected UnsupportedEncodingException"); + } + String s8 = new String(byteArray, 3, 3, charset); + String s9 = new String(byteArray, charset); + String s10 = new String(charArray); + String s11 = new String(charArray, 0, 4); + String s12 = new String(string); + String s13 = new String(stringBuffer); + String s14 = new String(codePoints, 1, 3); + String s15 = new String(stringBuilder); + } } |