Search code examples
javaopencv

Difference between Mat.n_delete() and Mat.n_release


I am using OpenCV with Java and because OpenCV has no idea about what the Java GC is doing, I have always been told that I need to release my Mat objects using Mat.release() to avoid memory leaks. Therefore, I have always been using try-finally:

// Suppose this is actually reading some image or similar
Mat mat = new Mat()

try {
    // Do something with mat
} finally {
    mat.release()
}

While debugging a memory leak (of which I have yet to find the cause), I had a look at the generated source code for Mat.java and found the following:

public class Mat {
    // ...
    
    public void release() {
        n_release(nativeObj);
    }

    // ...
    
    @Override
    protected void finalize() throws Throwable {
        n_delete(nativeObj);
        super.finalize();
    }

    // ...

So, in summary, release internally calls n_release and finalize calls n_delete. No matter the method called, after the method call, Mat.dataAddr() returns 0L either way.

My questions as a non-C++ developer are therefore the following:

  • What is the difference between n_release and n_delete?
  • Does n_delete actually free the memory associated with the Mat or does it merely delete the pointer to it?
  • Do I really need to call Mat.release() explicitly, or is a call to finalize() (implicitly done by the garbage collector) enough?

Edit: While debugging my memory leak, I also had a look at Core.merge() which looks like so:

public static void merge(List<Mat> mv, Mat dst) {
    Mat mv_mat = Converters.vector_Mat_to_Mat(mv);
    merge_0(mv_mat.nativeObj, dst.nativeObj);
}

It creates a temporary Mat object (called mv_mat) on which it never calls release() and because mv_mat is internal to the method, no external caller can ever call mv_mat.release(). I am therefore assuming that forgetting to call release() while not being recommended (due to the reliance on finalizers) does not constitute a memory leak by itself.


Solution

  • Difference between n_release and n_delete: n_release decrements the reference count and frees the resource if no references remain. n_delete directly frees the memory when the Java object is garbage collected.

    Does n_delete free memory?: Yes, n_delete is designed to free the allocated native memory, not just delete the pointer.

    Need to call Mat.release() explicitly?: Yes, you should explicitly call Mat.release() to manage memory efficiently. Relying on finalize() is not advisable due to its unpredictable nature and potential for delayed resource release. Explicitly releasing resources with Mat.release() ensures timely memory management and avoids memory leaks.