Include JNI details in the SIGQUIT output.
Also include the original command line (framework apps deliberately clobber
their argv[]).
Change-Id: I63e04cb637fa89764e8963f3d086806ae230e953
diff --git a/src/heap.cc b/src/heap.cc
index b4bc7ce..02e3ac7 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -51,7 +51,7 @@
}
}
-static bool GenerateImage(const std::string image_file_name) {
+static bool GenerateImage(const std::string& image_file_name) {
const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
std::vector<std::string> boot_class_path;
Split(boot_class_path_string, ':', boot_class_path);
@@ -660,7 +660,7 @@
void Heap::DumpForSigQuit(std::ostream& os) {
os << "Heap: " << GetPercentFree() << "% free, "
<< PrettySize(num_bytes_allocated_) << "/" << PrettySize(GetTotalMemory())
- << "; " << num_objects_allocated_ << " objects";
+ << "; " << num_objects_allocated_ << " objects\n";
}
size_t Heap::GetPercentFree() {
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index ccebca5..eacc73f 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -647,7 +647,7 @@
return LookupStringId(std::string(string));
}
-HprofStringId Hprof::LookupStringId(std::string string) {
+HprofStringId Hprof::LookupStringId(const std::string& string) {
StringMapIterator it = strings_.find(string);
if (it != strings_.end()) {
return it->second;
diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h
index bcdbef8..e2f7ce1 100644
--- a/src/hprof/hprof.h
+++ b/src/hprof/hprof.h
@@ -196,7 +196,7 @@
HprofClassObjectId LookupClassId(Class* c);
HprofStringId LookupStringId(String* string);
HprofStringId LookupStringId(const char* string);
- HprofStringId LookupStringId(std::string string);
+ HprofStringId LookupStringId(const std::string& string);
HprofStringId LookupClassNameId(Class* c);
static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut);
static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t* sizeOut);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 1e27604..846a717 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -659,6 +659,21 @@
STLDeleteValues(&libraries_);
}
+ void Dump(std::ostream& os) const {
+ bool first = true;
+ for (It it = libraries_.begin(); it != libraries_.end(); ++it) {
+ if (!first) {
+ os << ' ';
+ }
+ first = false;
+ os << it->first;
+ }
+ }
+
+ size_t size() const {
+ return libraries_.size();
+ }
+
SharedLibrary* Get(const std::string& path) {
It it = libraries_.find(path);
return (it == libraries_.end()) ? NULL : it->second;
@@ -698,7 +713,7 @@
}
private:
- typedef SafeMap<std::string, SharedLibrary*>::iterator It; // TODO: C++0x auto
+ typedef SafeMap<std::string, SharedLibrary*>::const_iterator It; // TODO: C++0x auto
SafeMap<std::string, SharedLibrary*> libraries_;
};
@@ -2783,6 +2798,34 @@
functions = enabled ? GetCheckJniInvokeInterface() : &gJniInvokeInterface;
}
+void JavaVMExt::DumpForSigQuit(std::ostream& os) {
+ os << "JNI: CheckJNI is " << (check_jni ? "on" : "off");
+ if (force_copy) {
+ os << " (with forcecopy)";
+ }
+ os << "; workarounds are " << (work_around_app_jni_bugs ? "on" : "off");
+ {
+ MutexLock mu(pins_lock);
+ os << "; pins=" << pin_table.Size();
+ }
+ {
+ MutexLock mu(globals_lock);
+ os << "; globals=" << globals.Capacity();
+ }
+ {
+ MutexLock mu(weak_globals_lock);
+ if (weak_globals.Capacity() > 0) {
+ os << " (plus " << weak_globals.Capacity() << " weak)";
+ }
+ }
+ os << '\n';
+
+ {
+ MutexLock mu(libraries_lock);
+ os << "Libraries: " << Dumpable<Libraries>(*libraries) << " (" << libraries->size() << ")\n";
+ }
+}
+
void JavaVMExt::DumpReferenceTables() {
{
MutexLock mu(globals_lock);
diff --git a/src/jni_internal.h b/src/jni_internal.h
index 312b754..e12a7cd 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -26,6 +26,7 @@
#include "reference_table.h"
#include "runtime.h"
+#include <iosfwd>
#include <string>
namespace art {
@@ -97,6 +98,8 @@
*/
void* FindCodeForNativeMethod(Method* m);
+ void DumpForSigQuit(std::ostream& os);
+
void DumpReferenceTables();
void SetCheckJniEnabled(bool enabled);
diff --git a/src/runtime.cc b/src/runtime.cc
index 8fe760e..18d40f5 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -491,10 +491,6 @@
parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
}
- LOG(INFO) << "Build type: "
- << (kIsDebugBuild ? "debug" : "optimized")
- << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off");
-
return parsed.release();
}
@@ -754,6 +750,7 @@
void Runtime::DumpForSigQuit(std::ostream& os) {
GetClassLinker()->DumpForSigQuit(os);
GetInternTable()->DumpForSigQuit(os);
+ GetJavaVM()->DumpForSigQuit(os);
GetHeap()->DumpForSigQuit(os);
os << "\n";
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 5a9bf4e..0703b61 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -38,6 +38,14 @@
namespace art {
+static bool ReadCmdLine(std::string& result) {
+ if (!ReadFileToString("/proc/self/cmdline", &result)) {
+ return false;
+ }
+ std::replace(result.begin(), result.end(), '\0', ' ');
+ return true;
+}
+
SignalCatcher::SignalCatcher(const std::string& stack_trace_file)
: stack_trace_file_(stack_trace_file),
lock_("SignalCatcher lock"),
@@ -45,6 +53,10 @@
thread_(NULL) {
SetHaltFlag(false);
+ // Stash the original command line for SIGQUIT reporting.
+ // By then, /proc/self/cmdline will have been rewritten to something like "system_server".
+ CHECK(ReadCmdLine(cmd_line_));
+
// Create a raw pthread; its start routine will attach to the runtime.
CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Run, this), "signal catcher thread");
@@ -109,11 +121,17 @@
os << "\n"
<< "----- pid " << getpid() << " at " << GetIsoDate() << " -----\n";
- std::string cmdline;
- if (ReadFileToString("/proc/self/cmdline", &cmdline)) {
- std::replace(cmdline.begin(), cmdline.end(), '\0', ' ');
- os << "Cmd line: " << cmdline << "\n";
+ std::string current_cmd_line;
+ if (ReadCmdLine(current_cmd_line) && current_cmd_line != cmd_line_) {
+ os << "Cmdline: " << current_cmd_line;
}
+ os << "\n";
+
+ if (current_cmd_line != cmd_line_) {
+ os << "Original command line: " << cmd_line_ << "\n";
+ }
+
+ os << "Build type: " << (kIsDebugBuild ? "debug" : "optimized") << "\n";
runtime->DumpForSigQuit(os);
diff --git a/src/signal_catcher.h b/src/signal_catcher.h
index 131b07c..da61ceb 100644
--- a/src/signal_catcher.h
+++ b/src/signal_catcher.h
@@ -52,6 +52,7 @@
ConditionVariable cond_;
pthread_t pthread_;
Thread* thread_;
+ std::string cmd_line_;
};
} // namespace art
diff --git a/src/thread_linux.cc b/src/thread_linux.cc
index 314668d..8eb8813 100644
--- a/src/thread_linux.cc
+++ b/src/thread_linux.cc
@@ -19,7 +19,7 @@
namespace art {
void Thread::DumpNativeStack(std::ostream&) const {
- // TODO: use glibc backtrace(3).
+ // TODO: use libcorkscrew; backtrace(3) only works for the calling thread.
}
void Thread::SetNativePriority(int) {