summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2015-05-19 20:30:23 -0700
committerJeff Hao <jeffhao@google.com>2015-05-20 18:32:14 -0700
commit15e9ad1d028d7f12cb598b075453173532a00d91 (patch)
treef31edd7f7e10d8372c452229b4f9eb749647864f /runtime
parent5d52f3dca52548f4a4598abd06432cad3dca6b8a (diff)
downloadandroid_art-15e9ad1d028d7f12cb598b075453173532a00d91.tar.gz
android_art-15e9ad1d028d7f12cb598b075453173532a00d91.tar.bz2
android_art-15e9ad1d028d7f12cb598b075453173532a00d91.zip
Intercept JNI invocation of String.<init> methods.
libmono uses JNI AllocObject and CallNonvirtualVoidMethod to create and initialize a string instead of using the recommended NewObject. This change adds an intercept to change the String.<init> call to a StringFactory call instead. Then, it uses the object id of the original string object referrer and maps it to the result of the StringFactory. Bug: 21288130 Change-Id: Ib4db402c178bc37188d5c5faf30b6e4fdc747b17
Diffstat (limited to 'runtime')
-rw-r--r--runtime/debugger.cc3
-rw-r--r--runtime/indirect_reference_table-inl.h9
-rw-r--r--runtime/indirect_reference_table.h11
-rw-r--r--runtime/jni_internal.cc49
-rw-r--r--runtime/jni_internal_test.cc3
-rw-r--r--runtime/reflection.cc47
-rw-r--r--runtime/reflection.h6
-rw-r--r--runtime/reflection_test.cc104
-rw-r--r--runtime/thread.cc6
9 files changed, 152 insertions, 86 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());
}