More SIGQUIT detail, earlier exit in AttachCurrentThread, handling recursive aborts, and reporting debug/optimized builds.
Change-Id: I932b49a8e92a91e340b4d98b8771dd4a41b61229
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9d8a1f1..a94607a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2800,6 +2800,12 @@
}
}
+void ClassLinker::DumpForSigQuit(std::ostream& os) const {
+ MutexLock mu(classes_lock_);
+ os << "Loaded classes: " << image_classes_.size() << " image classes; "
+ << classes_.size() << " allocated classes\n";
+}
+
size_t ClassLinker::NumLoadedClasses() const {
MutexLock mu(classes_lock_);
return classes_.size() + image_classes_.size();
diff --git a/src/class_linker.h b/src/class_linker.h
index a972b3b..03c8341 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -70,6 +70,8 @@
void DumpAllClasses(int flags) const;
+ void DumpForSigQuit(std::ostream& os) const;
+
size_t NumLoadedClasses() const;
// Resolve a String with the given index from the DexFile, storing the
diff --git a/src/intern_table.cc b/src/intern_table.cc
index 5de70d8..a848761 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -15,6 +15,13 @@
return strong_interns_.size() + weak_interns_.size();
}
+void InternTable::DumpForSigQuit(std::ostream& os) const {
+ MutexLock mu(intern_table_lock_);
+ os << "Intern table: " << strong_interns_.size() << " strong; "
+ << weak_interns_.size() << " weak; "
+ << image_strong_interns_.size() << " image strong\n";
+}
+
void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
MutexLock mu(intern_table_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
diff --git a/src/intern_table.h b/src/intern_table.h
index 86054b9..80f21e2 100644
--- a/src/intern_table.h
+++ b/src/intern_table.h
@@ -3,11 +3,12 @@
#ifndef ART_SRC_INTERN_TABLE_H_
#define ART_SRC_INTERN_TABLE_H_
-#include "unordered_map.h"
+#include <iosfwd>
#include "heap.h"
#include "mutex.h"
#include "object.h"
+#include "unordered_map.h"
namespace art {
@@ -49,6 +50,8 @@
void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
+ void DumpForSigQuit(std::ostream& os) const;
+
private:
typedef std::tr1::unordered_multimap<int32_t, String*> Table;
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 1f3124c..45eedb8 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -447,6 +447,21 @@
return JNI_ERR;
}
+ // Return immediately if we're already one with the VM.
+ Thread* self = Thread::Current();
+ if (self != NULL) {
+ *p_env = self->GetJniEnv();
+ return JNI_OK;
+ }
+
+ Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->runtime;
+
+ // No threads allowed in zygote mode.
+ if (runtime->IsZygote()) {
+ LOG(ERROR) << "Attempt to attach a thread in the zygote";
+ return JNI_ERR;
+ }
+
JavaVMAttachArgs* in_args = static_cast<JavaVMAttachArgs*>(thr_args);
JavaVMAttachArgs args;
if (thr_args == NULL) {
@@ -466,7 +481,6 @@
}
CHECK_GE(args.version, JNI_VERSION_1_2);
- Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->runtime;
runtime->AttachCurrentThread(args.name, as_daemon);
*p_env = Thread::Current()->GetJniEnv();
return JNI_OK;
diff --git a/src/runtime.cc b/src/runtime.cc
index 54d7ec6..c1060f7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -76,8 +76,15 @@
instance_ = NULL;
}
+static bool gAborting = false;
+
struct AbortState {
void Dump(std::ostream& os) {
+ if (gAborting) {
+ os << "Runtime aborting --- recursively, so no thread-specific detail!\n";
+ return;
+ }
+ gAborting = true;
os << "Runtime aborting...\n";
Thread* self = Thread::Current();
if (self == NULL) {
@@ -372,7 +379,13 @@
parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
}
- LOG(INFO) << "CheckJNI is " << (parsed->check_jni_ ? "on" : "off");
+ LOG(INFO) << "Build type: "
+#ifndef NDEBUG
+ << "debug"
+#else
+ << "optimized"
+#endif
+ << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off");
return parsed.release();
}
@@ -612,14 +625,8 @@
void Runtime::Dump(std::ostream& os) {
// TODO: dump other runtime statistics?
- os << "Loaded classes: " << class_linker_->NumLoadedClasses() << "\n";
- os << "Intern table size: " << GetInternTable()->Size() << "\n";
- // LOGV("VM stats: meth=%d ifld=%d sfld=%d linear=%d",
- // gDvm.numDeclaredMethods,
- // gDvm.numDeclaredInstFields,
- // gDvm.numDeclaredStaticFields,
- // gDvm.pBootLoaderAlloc->curOffset);
- // LOGI("GC precise methods: %d", dvmPointerSetGetCount(gDvm.preciseMethods));
+ GetClassLinker()->DumpForSigQuit(os);
+ GetInternTable()->DumpForSigQuit(os);
os << "\n";
thread_list_->Dump(os);
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 4e8628d..f25a9ba 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -105,7 +105,6 @@
std::ostringstream os;
os << "\n"
- << "\n"
<< "----- pid " << getpid() << " at " << GetIsoDate() << " -----\n";
std::string cmdline;
diff --git a/src/thread.cc b/src/thread.cc
index 538aaa8..e43aa14 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -246,6 +246,8 @@
}
void Thread::Attach(const Runtime* runtime) {
+ CHECK(Thread::Current() == NULL);
+
InitCpu();
InitFunctionPointers();
InitCardTable();
@@ -263,21 +265,18 @@
}
Thread* Thread::Attach(const Runtime* runtime, const char* name, bool as_daemon) {
- Thread* self = Thread::Current();
- if (self == NULL) {
- self = new Thread;
- self->Attach(runtime);
+ Thread* self = new Thread;
+ self->Attach(runtime);
- self->SetState(Thread::kNative);
+ self->SetState(Thread::kNative);
- // If we're the main thread, ClassLinker won't be created until after we're attached,
- // so that thread needs a two-stage attach. Regular threads don't need this hack.
- if (self->thin_lock_id_ != ThreadList::kMainId) {
- self->CreatePeer(name, as_daemon);
- }
-
- self->GetJniEnv()->locals.AssertEmpty();
+ // If we're the main thread, ClassLinker won't be created until after we're attached,
+ // so that thread needs a two-stage attach. Regular threads don't need this hack.
+ if (self->thin_lock_id_ != ThreadList::kMainId) {
+ self->CreatePeer(name, as_daemon);
}
+
+ self->GetJniEnv()->locals.AssertEmpty();
return self;
}