Investigate objects retained through JNI references

Capture a bounded graph of JNI-rooted Android objects to investigate retention in your Android app.

JNI Reference Diagnostics helps investigate which Java objects remain reachable through JNI roots when reference counts need explanation. Capture a bounded, redacted graph for a focused retention investigation.

The Android suite exposes the Read policy jni_references.capture_graph tool.

Install

The aggregate ai.ansight:ansight-android package includes the suite. For a narrow Debug-only integration:

dependencies {
    debugImplementation("ai.ansight:ansight-tools-jnireferencediagnostics-android:latest.release")
}

Register and Bound the Suite

import ai.ansight.runtime.AnsightOptions
import ai.ansight.tools.jnireferencediagnostics.withJniReferenceDiagnosticsTools

val options = AnsightOptions.createBuilder()
    .withJniReferenceDiagnosticsTools {
        maximumGraphNodes(4096)
        maximumGraphEdges(8192)
        maximumGraphDepth(12)
    }
    .withReadOnlyToolAccess()
    .build()

Configured maxima default to 2,048 nodes, 4,096 edges, and depth 8 and are clamped to 8,192 nodes, 16,384 edges, and depth 16. An individual tool call defaults to the smaller 512 nodes, 1,024 edges, and depth 4 and can request any value up to the configured maxima.

{
  "toolId": "jni_references.capture_graph",
  "arguments": {
    "maxNodes": 1024,
    "maxEdges": 2048,
    "maxDepth": 6
  }
}

Result and Redaction

The tool asks ART for a temporary HPROF snapshot, indexes it with Shark, and walks only objects reachable from JNI global, local, or monitor roots. The result includes:

  • capture-local opaque root and object ids
  • root kind and bounded local/monitor metadata
  • class names, object kinds, shallow sizes, and depth
  • field or array reference edges
  • capture limits, counts, duration, HPROF size, and truncation reasons

It deliberately omits raw heap ids, JNI handle addresses, primitive values, strings, and field values. Opaque ids are valid only for the returned capture.

Availability and Cost

Tool discovery reports current runtime availability. The tool requires an initialized Android Application; an unavailable catalog entry reports android_application_unavailable and the required state rather than waiting for invocation to fail.

Heap dumping briefly pauses the app and indexing uses additional memory. Capture is serialized, intended only for explicit development diagnostics, and deletes the temporary HPROF file after graph construction. Do not call it during trend measurements or expose it outside a trusted development build.

Use Trends Telemetry with withJniReferenceCountTracking() for a lightweight trend. Invoke this tool only when the trend warrants a bounded object-graph investigation.