Improving ART debugging and printing VmSize when OOM occurs
VmSize debugging information is added to quickly identify whether
the process address space or the system memory is insufficient
Test: 1 Manually trigger an OOM exception
2 Checking whether the keyword VmSize exists in the OOM
exception log
3 art/test.py --host --64 -r
Signed-off-by: Wei Li <sirius.liwei@huawei.com>
Signed-off-by: Jinguang Dong <dongjinguang@huawei.com>
Change-Id: I0ea53f5136c06aba27712f95335ca722e7d30d95
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc
index 2242fe8..0f172fd 100644
--- a/libartbase/base/utils.cc
+++ b/libartbase/base/utils.cc
@@ -24,6 +24,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <fstream>
#include <memory>
#include "android-base/file.h"
@@ -213,4 +214,25 @@
}
}
+std::string GetProcessStatus(const char* key) {
+ // Build search pattern of key and separator.
+ std::string pattern(key);
+ pattern.push_back(':');
+
+ // Search for status lines starting with pattern.
+ std::ifstream fs("/proc/self/status");
+ std::string line;
+ while (std::getline(fs, line)) {
+ if (strncmp(pattern.c_str(), line.c_str(), pattern.size()) == 0) {
+ // Skip whitespace in matching line (if any).
+ size_t pos = line.find_first_not_of(" \t", pattern.size());
+ if (UNLIKELY(pos == std::string::npos)) {
+ break;
+ }
+ return std::string(line, pos);
+ }
+ }
+ return "<unknown>";
+}
+
} // namespace art
diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h
index e6a0459..9c71055 100644
--- a/libartbase/base/utils.h
+++ b/libartbase/base/utils.h
@@ -216,6 +216,11 @@
}
}
+// Lookup value for a given key in /proc/self/status. Keys and values are separated by a ':' in
+// the status file. Returns value found on success and "<unknown>" if the key is not found or
+// there is an I/O error.
+std::string GetProcessStatus(const char* key);
+
} // namespace art
#endif // ART_LIBARTBASE_BASE_UTILS_H_
diff --git a/libartbase/base/utils_test.cc b/libartbase/base/utils_test.cc
index 892d1fd..9bd50c3 100644
--- a/libartbase/base/utils_test.cc
+++ b/libartbase/base/utils_test.cc
@@ -126,4 +126,12 @@
EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer + 57, buffer, buffer_end), nullptr);
}
+TEST_F(UtilsTest, GetProcessStatus) {
+ EXPECT_EQ("utils_test", GetProcessStatus("Name"));
+ EXPECT_EQ("R (running)", GetProcessStatus("State"));
+ EXPECT_EQ("<unknown>", GetProcessStatus("tate"));
+ EXPECT_EQ("<unknown>", GetProcessStatus("e"));
+ EXPECT_EQ("<unknown>", GetProcessStatus("Dummy"));
+}
+
} // namespace art
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 8a8f537..ae7a1a7 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3147,8 +3147,10 @@
}
void Thread::ThrowOutOfMemoryError(const char* msg) {
- LOG(WARNING) << StringPrintf("Throwing OutOfMemoryError \"%s\"%s",
- msg, (tls32_.throwing_OutOfMemoryError ? " (recursive case)" : ""));
+ LOG(WARNING) << "Throwing OutOfMemoryError "
+ << '"' << msg << '"'
+ << " (VmSize " << GetProcessStatus("VmSize")
+ << (tls32_.throwing_OutOfMemoryError ? ", recursive case)" : ")");
if (!tls32_.throwing_OutOfMemoryError) {
tls32_.throwing_OutOfMemoryError = true;
ThrowNewException("Ljava/lang/OutOfMemoryError;", msg);