getRuntimeStat() support (ART).
Export some runtime stats (currently GC stats) via
VMDebug.getRuntimeStat().
Added several new GC stats such as blocking GC counts and GC count
histograms.
Bug: 19825248
Change-Id: I8ece9ed241dc3982dfd983d7159090ba82940dce
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 2724d91..876e29a 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -19,6 +19,9 @@
#include <string.h>
#include <unistd.h>
+#include <sstream>
+
+#include "base/histogram-inl.h"
#include "class_linker.h"
#include "common_throws.h"
#include "debugger.h"
@@ -329,6 +332,123 @@
env->ReleasePrimitiveArrayCritical(data, arr, 0);
}
+// The runtime stat names for VMDebug.getRuntimeStat().
+enum class VMDebugRuntimeStatId {
+ kArtGcGcCount = 0,
+ kArtGcGcTime,
+ kArtGcBytesAllocated,
+ kArtGcBytesFreed,
+ kArtGcBlockingGcCount,
+ kArtGcBlockingGcTime,
+ kArtGcGcCountRateHistogram,
+ kArtGcBlockingGcCountRateHistogram,
+ kNumRuntimeStats,
+};
+
+static jobject VMDebug_getRuntimeStatInternal(JNIEnv* env, jclass, jint statId) {
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ switch (static_cast<VMDebugRuntimeStatId>(statId)) {
+ case VMDebugRuntimeStatId::kArtGcGcCount: {
+ std::string output = std::to_string(heap->GetGcCount());
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcGcTime: {
+ std::string output = std::to_string(NsToMs(heap->GetGcTime()));
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcBytesAllocated: {
+ std::string output = std::to_string(heap->GetBytesAllocatedEver());
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcBytesFreed: {
+ std::string output = std::to_string(heap->GetBytesFreedEver());
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcBlockingGcCount: {
+ std::string output = std::to_string(heap->GetBlockingGcCount());
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcBlockingGcTime: {
+ std::string output = std::to_string(NsToMs(heap->GetBlockingGcTime()));
+ return env->NewStringUTF(output.c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcGcCountRateHistogram: {
+ std::ostringstream output;
+ heap->DumpGcCountRateHistogram(output);
+ return env->NewStringUTF(output.str().c_str());
+ }
+ case VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram: {
+ std::ostringstream output;
+ heap->DumpBlockingGcCountRateHistogram(output);
+ return env->NewStringUTF(output.str().c_str());
+ }
+ default:
+ return nullptr;
+ }
+}
+
+static bool SetRuntimeStatValue(JNIEnv* env, jobjectArray result, VMDebugRuntimeStatId id,
+ std::string value) {
+ ScopedLocalRef<jstring> jvalue(env, env->NewStringUTF(value.c_str()));
+ if (jvalue.get() == nullptr) {
+ return false;
+ }
+ env->SetObjectArrayElement(result, static_cast<jint>(id), jvalue.get());
+ return true;
+}
+
+static jobjectArray VMDebug_getRuntimeStatsInternal(JNIEnv* env, jclass) {
+ jobjectArray result = env->NewObjectArray(
+ static_cast<jint>(VMDebugRuntimeStatId::kNumRuntimeStats),
+ WellKnownClasses::java_lang_String,
+ nullptr);
+ if (result == nullptr) {
+ return nullptr;
+ }
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCount,
+ std::to_string(heap->GetGcCount()))) {
+ return nullptr;
+ }
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcTime,
+ std::to_string(NsToMs(heap->GetGcTime())))) {
+ return nullptr;
+ }
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesAllocated,
+ std::to_string(heap->GetBytesAllocatedEver()))) {
+ return nullptr;
+ }
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBytesFreed,
+ std::to_string(heap->GetBytesFreedEver()))) {
+ return nullptr;
+ }
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCount,
+ std::to_string(heap->GetBlockingGcCount()))) {
+ return nullptr;
+ }
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcTime,
+ std::to_string(NsToMs(heap->GetBlockingGcTime())))) {
+ return nullptr;
+ }
+ {
+ std::ostringstream output;
+ heap->DumpGcCountRateHistogram(output);
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcGcCountRateHistogram,
+ output.str())) {
+ return nullptr;
+ }
+ }
+ {
+ std::ostringstream output;
+ heap->DumpBlockingGcCountRateHistogram(output);
+ if (!SetRuntimeStatValue(env, result, VMDebugRuntimeStatId::kArtGcBlockingGcCountRateHistogram,
+ output.str())) {
+ return nullptr;
+ }
+ }
+ return result;
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
NATIVE_METHOD(VMDebug, crash, "()V"),
@@ -359,6 +479,8 @@
NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "!()J"),
+ NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
+ NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;")
};
void register_dalvik_system_VMDebug(JNIEnv* env) {