Version: Unity 6.5 Alpha (6000.5)
LanguageEnglish
  • C#

AndroidJNI.DumpReferenceTables

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

Declaration

public static bool DumpReferenceTables();

Returns

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

Description

Dumps JNI local/global reference tables to logcat.

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.