Various runtime/JNI related fixes.
NewObject returns NULL if exception is thrown in constructor.
Allocate the peer then call constructor to ensure peer_ field is
initialized.
Change thread state for AddFinalizer and pass current thread through for
ease.
Change-Id: Ib578b6d44b08aef10fde5d8bc27cc6a2acbf6fae
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 9b6c74e..80b21e2 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -144,6 +144,7 @@
}
// Check early that the result of compilation can be written
+ // TODO: implement a proper locking scheme here, probably hold onto the open file..
if (OS::FileExists(oat_filename.c_str())) {
// File exists, check we can write to it
UniquePtr<File> file(OS::OpenFile(oat_filename.c_str(), true));
diff --git a/src/heap.cc b/src/heap.cc
index 9561c48..57a3ce2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -734,12 +734,13 @@
return ref;
}
-void Heap::AddFinalizerReference(Object* object) {
+void Heap::AddFinalizerReference(Thread* self, Object* object) {
+ ScopedThreadStateChange tsc(self, Thread::kRunnable);
static Method* FinalizerReference_add =
java_lang_ref_FinalizerReference_->FindDirectMethod("add", "(Ljava/lang/Object;)V");
DCHECK(FinalizerReference_add != NULL);
Object* args[] = { object };
- FinalizerReference_add->Invoke(Thread::Current(), NULL, reinterpret_cast<byte*>(&args), NULL);
+ FinalizerReference_add->Invoke(self, NULL, reinterpret_cast<byte*>(&args), NULL);
}
void Heap::EnqueueClearedReferences(Object** cleared) {
diff --git a/src/heap.h b/src/heap.h
index 923b015..8897405 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -32,6 +32,7 @@
class Mutex;
class Object;
class Space;
+class Thread;
class HeapBitmap;
class Heap {
@@ -194,7 +195,7 @@
// dlmalloc_walk_heap-compatible heap walker.
static void WalkHeap(void(*callback)(const void*, size_t, const void*, size_t, void*), void* arg);
- static void AddFinalizerReference(Object* object);
+ static void AddFinalizerReference(Thread* self, Object* object);
static size_t GetBytesAllocated() { return num_bytes_allocated_; }
static size_t GetObjectsAllocated() { return num_objects_allocated_; }
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 5052773..1f3124c 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -965,7 +965,11 @@
}
jobject local_result = AddLocalReference<jobject>(env, result);
CallNonvirtualVoidMethodV(env, local_result, java_class, mid, args);
- return local_result;
+ if (!ts.Self()->IsExceptionPending()) {
+ return local_result;
+ } else {
+ return NULL;
+ }
}
static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID mid, jvalue* args) {
@@ -980,7 +984,11 @@
}
jobject local_result = AddLocalReference<jobjectArray>(env, result);
CallNonvirtualVoidMethodA(env, local_result, java_class, mid, args);
- return local_result;
+ if (!ts.Self()->IsExceptionPending()) {
+ return local_result;
+ } else {
+ return NULL;
+ }
}
static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
diff --git a/src/object.cc b/src/object.cc
index 2bb6d2d..9cc0e3a 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -43,7 +43,7 @@
memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
if (c->IsFinalizable()) {
- Heap::AddFinalizerReference(copy.get());
+ Heap::AddFinalizerReference(Thread::Current(), copy.get());
}
return copy.get();
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 3c10fc3..9653d28 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -44,7 +44,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Class* c = o->GetClass();
if (UNLIKELY(c->IsFinalizable())) {
- Heap::AddFinalizerReference(o);
+ Heap::AddFinalizerReference(self, o);
}
/*
* NOTE: once debugger/profiler support is added, we'll need to check
diff --git a/src/thread.cc b/src/thread.cc
index 983486a..af48c35 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -295,11 +295,16 @@
jboolean thread_is_daemon = as_daemon;
ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Thread"));
- jmethodID mid = env->GetMethodID(c.get(), "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
-
- ScopedLocalRef<jobject> peer(env,
- env->NewObject(c.get(), mid, thread_group.get(), thread_name.get(), thread_priority, thread_is_daemon));
+ ScopedLocalRef<jobject> peer(env, env->AllocObject(c.get()));
peer_ = DecodeJObject(peer.get());
+ if (peer_ == NULL) {
+ CHECK(IsExceptionPending());
+ // TODO: signal failure to caller
+ return;
+ }
+ jmethodID mid = env->GetMethodID(c.get(), "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
+ env->CallNonvirtualVoidMethod(peer.get(), c.get(), mid, thread_group.get(), thread_name.get(), thread_priority, thread_is_daemon);
+ CHECK(!IsExceptionPending());
SetVmData(peer_, Thread::Current());
SirtRef<String> peer_thread_name(GetName());