Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


DumpReferenceTables()

Dumps JNI local/global reference tables to logcat.
Read time 2 minutesLast updated 10 days ago

Definition

  • Type: Method
  • Namespace: UnityEngine
  • Assembly: UnityEngine.AndroidJNIModule
public static bool DumpReferenceTables()

Returns

Type

Description

boolReturns true if
android.os.Debug.dumpReferenceTables()
is accessible and was invoked successfully.

Remarks

Used to diagnose JNI reference leaks and other reference-table corruption.
Note: This function attempts to invoke the undocumented
android.os.Debug.dumpReferenceTables()
method. If that method is unavailable, AndroidJNI.DumpReferenceTables has no effect.
Each AndroidJavaObject instance creates a global JNI reference, which remains until the object is explicitly disposed or collected by the C# garbage collector. Failing to dispose an AndroidJavaObject can lead to
java.lang.OutOfMemoryError
if the process reaches the maximum number of allowed JNI references.
Call AndroidJNI.DumpReferenceTables before and after the code which you want to test, and compare two outputs to determine if you're leaking.
Additional Resources: Local and global JNI references.
using UnityEngine;using UnityEngine.Android;public class Sample : MonoBehaviour{ void TestLeaks() { using var motionEventClass = new AndroidJavaClass("android.view.MotionEvent"); AndroidJNI.DumpReferenceTables(); for (int i = 0; i < 100; i++) { var window = AndroidApplication.currentActivity.Call<AndroidJavaObject>("getWindow"); // Do something with window // If you'll fail to call Dispose(), jni reference will be kept alive until C# garbage collector collects 'window' object (which might not happen soon) // There's a limited amount of max jni references you can have, it depends on the Android version, it's always better to Dispose or use 'using' keyword to release jni reference. // window.Dispose(); } AndroidJNI.DumpReferenceTables(); } private void OnGUI() { GUILayout.Space(100); if (GUILayout.Button("TestLeaks", GUILayout.Height(200), GUILayout.Width(Screen.width))) TestLeaks(); }}
The sample above will produce the following log:
--- reference table dump ---
local reference table dump:
Last 1 entries (of 1):
0: 0x242c298 java.lang.Class<com.unity3d.player.ReflectionHelper>
Summary:
1 of java.lang.Class
monitors reference table dump:
(empty)
global reference table dump:
Last 10 entries (of 744):
743: 0x6faef540 java.lang.Class<com.android.internal.policy.PhoneWindow>
742: 0x2348060 com.android.internal.policy.PhoneWindow
741: 0x6faef540 java.lang.Class<com.android.internal.policy.PhoneWindow>
740: 0x2348060 com.android.internal.policy.PhoneWindow
739: 0x6faef540 java.lang.Class<com.android.internal.policy.PhoneWindow>
738: 0x2348060 com.android.internal.policy.PhoneWindow
737: 0x6faef540 java.lang.Class<com.android.internal.policy.PhoneWindow>
736: 0x2348060 com.android.internal.policy.PhoneWindow
735: 0x6faef540 java.lang.Class<com.android.internal.policy.PhoneWindow>
734: 0x2348060 com.android.internal.policy.PhoneWindow.
Notice global reference table dump contains a lot of
com.android.internal.policy.PhoneWindow
instances, to fix the leak, you need to properly dispose
window
object by calling
Dispose
method.