Add a reference table dump call.
This adds a hidden method to android.os.Debug that causes the contents
of various reference tables to be dumped. Currently it's the local,
global, and pinned array tables from JNI.
Bug 2075355
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
index 365388a..f9411ca 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -284,10 +284,18 @@
public static native boolean cacheRegisterMap(String classAndMethodDesc);
/**
- * Crashes the VM. Seriously. Dumps the stack trace for the current
- * thread and then aborts the VM so you can see the native stack trace.
- * Useful for figuring out how you got somewhere when lots of native
- * code is involved.
+ * Dumps the contents of the VM reference tables (e.g. JNI locals and
+ * globals) to the log file.
+ *
+ * @hide
+ */
+ public static native void dumpReferenceTables();
+
+ /**
+ * Crashes the VM. Seriously. Dumps the interpreter stack trace for
+ * the current thread and then aborts the VM so you can see the native
+ * stack trace. Useful for figuring out how you got somewhere when
+ * lots of native code is involved.
*
* @hide
*/
diff --git a/vm/Jni.c b/vm/Jni.c
index 54a1f45..1dcea10 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -1123,6 +1123,27 @@
}
/*
+ * Dump the contents of the JNI reference tables to the log file.
+ *
+ * We only dump the local refs associated with the current thread.
+ */
+void dvmDumpJniReferenceTables(void)
+{
+ Thread* self = dvmThreadSelf();
+ JNIEnv* env = self->jniEnv;
+ ReferenceTable* pLocalRefs = getLocalRefTable(env);
+
+#ifdef USE_INDIRECT_REF
+ dvmDumpIndirectRefTable(pLocalRefs, "JNI local");
+ dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
+#else
+ dvmDumpReferenceTable(pLocalRefs, "JNI local");
+ dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
+#endif
+ dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
+}
+
+/*
* GC helper function to mark all JNI global references.
*
* We're currently handling the "pin" table here too.
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index 3c15ce4..302dcb0 100644
--- a/vm/JniInternal.h
+++ b/vm/JniInternal.h
@@ -201,6 +201,12 @@
*/
void dvmReleaseJniMonitors(Thread* self);
+/*
+ * Dump the contents of the JNI reference tables to the log file.
+ *
+ * The local ref tables associated with other threads are not included.
+ */
+void dvmDumpJniReferenceTables(void);
/*
* This mask is applied to weak global reference values returned to
diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.c
index a8010a2..b47d775 100644
--- a/vm/ReferenceTable.c
+++ b/vm/ReferenceTable.c
@@ -213,7 +213,7 @@
int i;
if (count == 0) {
- LOGW("Reference table has no entries\n");
+ LOGW("%s reference table has no entries\n", descr);
return;
}
assert(count > 0);
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index 8aa371d..c2439a3 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -699,6 +699,23 @@
}
/*
+ * static void dumpReferenceTables()
+ */
+static void Dalvik_dalvik_system_VMDebug_dumpReferenceTables(const u4* args,
+ JValue* pResult)
+{
+ UNUSED_PARAMETER(args);
+ UNUSED_PARAMETER(pResult);
+
+ LOGI("--- reference table dump ---\n");
+ dvmDumpJniReferenceTables();
+ // could dump thread's internalLocalRefTable, probably not useful
+ // ditto for thread's jniMonitorRefTable
+ LOGI("---\n");
+ RETURN_VOID();
+}
+
+/*
* static void crash()
*
* Dump the current thread's interpreted stack and abort the VM. Useful
@@ -765,6 +782,8 @@
Dalvik_dalvik_system_VMDebug_dumpHprofData },
{ "cacheRegisterMap", "(Ljava/lang/String;)Z",
Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
+ { "dumpReferenceTables", "()V",
+ Dalvik_dalvik_system_VMDebug_dumpReferenceTables },
{ "crash", "()V",
Dalvik_dalvik_system_VMDebug_crash },
{ NULL, NULL, NULL },