Mobile Development 20 min read

Android JVMTI: Runtime Monitoring and Profiling Techniques

By patching ART’s internal debug flags to enable JVMTI on non‑debuggable apps, the authors created TBProfiler, a lightweight Android profiling tool that uses JVMTI’s event callbacks to trace method calls, thread and exception events, lock contention, and memory allocations, producing a compact mini‑hprof for production‑grade runtime monitoring and analysis.

DaTaobao Tech
DaTaobao Tech
DaTaobao Tech
Android JVMTI: Runtime Monitoring and Profiling Techniques

JVMTI (JVM Tool Interface) is a native programming interface provided by the Android Runtime (ART) that allows developers to debug, monitor, and modify Java applications at runtime. Starting from Android 8.0 (API 26) the interface is exposed as the ART Tooling Interface (ART TI).

The interface offers several powerful capabilities, including runtime state monitoring, class redefinition, object allocation and garbage‑collection tracking, heap traversal, stack inspection, and the ability to pause or resume all threads.

In standard Android builds JVMTI agents can only be attached to debuggable applications (android:debuggable="true"). This restriction severely limits the usefulness of JVMTI for production monitoring because release builds are not debuggable.

Two runtime flags control this restriction: gJdwpAllowed (managed by Dbg::IsJdwpAllowed() ) and is_java_debuggable_ (exposed via Runtime::IsJavaDebuggable() ). Both flags are initialized in ZygoteHooks_nativePostForkChild . By locating the symbols of SetJdwpAllowed in libart.so with dlsym and patching the memory addresses of these flags, the debugger can be enabled at runtime even for non‑debuggable apps.

Typical code used to load an agent and modify the flags looks like:

dalvikvm -Xplugin:libopenjdkjvmti.so -agentpath:/path/to/agent/libagent.so …
adb shell 'am attach-agent com.example.app/code_cache/libfieldnulls.so=Ljava/lang/Class;.name:Ljava/lang/String;'
static bool EnsureJvmtiPlugin(Runtime* runtime, std::string* error_msg) { … }

Based on these techniques the team built TBProfiler , an Android‑side profiling tool that wraps JVMTI to provide:

Method entry/exit tracing for performance analysis.

Thread creation/destruction and class‑load events.

Exception and uncaught‑exception callbacks.

Main‑thread lock contention detection using monitor and mutex information.

Memory allocation, free, and GC start/finish callbacks for heap monitoring.

Memory monitoring is implemented via JVMTI callbacks such as callback_->objectAlloc and callback_->objectFree . The collected data can be aggregated into a lightweight “mini‑hprof” format (≈150 KB after zstd compression) that records object IDs, class names, sizes, and reference relationships, enabling fast offline analysis of large‑memory allocations and potential leaks.

Although generating a full HPROF file through JVMTI is slower than the built‑in Android dump, the custom mini‑hprof provides sufficient information for most production diagnostics while keeping overhead low.

In summary, by bypassing the debug‑only restriction and leveraging JVMTI’s rich event model, TBProfiler offers a practical solution for runtime monitoring, performance profiling, and memory analysis on release Android applications, paving the way for more comprehensive on‑device diagnostics.

AndroidJVMTImemory analysisprofilingruntime monitoring
DaTaobao Tech
Written by

DaTaobao Tech

Official account of DaTaobao Technology

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.