# DumpReferenceTables()

> Dumps JNI local/global reference tables to logcat.

## Definition

* **Type:** Method
* **Namespace:** [UnityEngine](/engine/6000.7/script-reference/unityengine.md)
* **Assembly:** UnityEngine.AndroidJNIModule

```csharp
public static bool DumpReferenceTables()
```

### Returns

| Type                                                          | Description                                                                                          |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| [bool](https://learn.microsoft.com/dotnet/api/system.boolean) | Returns 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](/engine/6000.7/script-reference/unityengine/androidjni/dumpreferencetables.md) has no effect.

Each [AndroidJavaObject](/engine/6000.7/script-reference/unityengine/androidjavaobject.md) 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](/engine/6000.7/script-reference/unityengine/androidjavaobject.md) can lead to `java.lang.OutOfMemoryError` if the process reaches the maximum number of allowed JNI references.

Call [AndroidJNI.DumpReferenceTables](/engine/6000.7/script-reference/unityengine/androidjni/dumpreferencetables.md) before and after the code which you want to test, and compare two outputs to determine if you're leaking.

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.

Additional Resources: [Local and global JNI references.](https://docs.oracle.com/en/java/javase/21/docs/specs/jni/design.html#:~:text=The%20JNI%20divides%20object%20references,until%20they%20are%20explicitly%20freed.)

### Examples

```csharp
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();
    }
}
```
