How is memory freed up when native libraries are called from Java and Python?

I use Java shells for OpenCV. I used to use Python wrappers too. I read the following about JNI:

The JNI framework does not provide any automatic garbage collection for non-JVM
memory resources allocated by code executing on the native side.

I was wondering how freed up memory dynamically allocated using native libraries and when using Java wrappers and Python wrappers?

+3
source share
2 answers

As part of the JNI, I do not provide automatic garbage collection for external resources, but there will be wrappers providing bindings for the language.

Python , API C python . Py_INCREF() PyObject * , , , Py_DECREF() . (, - , ).

Java (JVM) , JNI, . Python, (*env)->DeleteLocalRef() (*env)->Release...() ( ), JNI.

, C foo:

// foo.h
typedef struct {
  char * bar;
} foo;

foo * foo_new(const char * bar);
void foo_delete(foo * self);

// foo.c
#include <stdlib.h>
#include <string.h>
#include "foo.h"

foo * foo_new(const char * bar) {
  // Allocate foo.
  foo * self = malloc(sizeof(foo));
  if (self == NULL) {
    return NULL;
  }
  memset(self, 0, sizeof(foo));
  // Copy bar to foo.
  size_t bar_len = strlen(bar);
  char * bar_copy = malloc(sizeof(char) * (bar_len + 1));
  if (bar_copy == NULL) {
    foo_delete(self);
    return NULL;
  }
  strncpy(bar_copy, bar, bar_len);
  bar_copy[bar_len] = '\0';
  self->bar = bar_copy;
  // Return foo pointer.
  return self;
}

void foo_delete(foo * self) {
  if (self == NULL) {
    return;
  }
  // Free bar.
  if (self->bar != NULL) {
    free(self->bar);
    self->bar = NULL;
  }
  // Free foo.
  free(self);
}

, Python foo, Python, . Python Python.

// pyfoo.c
#include <Python.h>
#include "foo.h"

// class PyFoo wraps struct foo.
typedef struct {
  PyObject_HEAD;
  foo * foo;
} PyFoo;

static PyObject * PyFoo_new(PyTypeObject * type, PyObject * args, PyObject * kwargs) {
  // Parse bar from arguments.
  const char * bar;
  if (!PyArg_ParseTuple(args, "s", &bar)) {
    return NULL;
  }
  // Allocate PyFoo.
  PyFoo * self;
  self = (PyFoo *)type->tp_alloc(type, 0);
  if (self == NULL) {
    return NULL;
  }
  // Create internal foo with bar.
  self->foo = foo_new(bar);
  if (self->foo == NULL) {
    Py_DECREF(self);
    return NULL;
  }
  // Return PyFoo instance.
  return (PyObject *)self;
}

static void PyFoo_dealloc(PyFoo * self) {
  // Delete internal foo pointer.
  foo_delete(self->foo);
  // Free python object.
  self->ob_type->tp_free((PyObject *)self);
}

static PyObject * PyFoo_bar(PyFoo * self) {
  // Return a copy of bar.
  return (PyObject *)PyString_FromString(self->foo->bar)
}

static PyMethodDef PyFoo_methods[] = {
  {"foo", (PyCFunction)PyFoo_bar, METH_NOARGS, "Returns foo."},
  {NULL}, // Sentinel.
};

foo Java, Java . JNI (, , ). ( Java), .

// Foo.java
public class Foo {

  private long foo_ptr;

  public Foo(String bar) {
    // Create internal foo with bar.
    this.foo_ptr = this.foo_new(bar)
  }

  protected void finalize() {
    // Delete internal foo.
    this.foo_delete(this.foo_ptr);
  }

  public String getBar() {
    // Return a copy of bar.
    return this.foo_bar(this.foo_ptr);
  }

  static {
    System.loadLibrary("javafoo");
  }

  private native long foo_new(String bar);
  private native void foo_delete(long foo_ptr);
  private native String foo_bar(long foo);
}

// javafoo.c
#include <jni.h>
#include "foo.h"

JNIEXPORT jlong JNICALL Java_Foo_foo_new(JNIEnv * env, jstring jbar) {
  // Convert java string to c string.
  char * bar = (*env)->GetStringUTFChars(env, jbar, NULL);
  if (bar == NULL) {
    return 0;
  }
  // Create internal foo with bar.
  foo * self = foo_new(bar);
  if (self == NULL) {
    (*env)->ReleaseStringUTFChars(env, jbar, bar);
    return 0;
  }
  // Delete bar c string.
  (*env)->ReleaseStringUTFChars(env, jbar, bar);
  // Return foo pointer as long.
  return (jlong)self;
}

JNIEXPORT void JNICALL Java_Foo_foo_delete(JNIEnv * env, jlong foo_ptr) {
  // Convert foo pointer from long.
  foo * self = (foo *)foo_ptr;
  // Delete internal foo.
  foo_delete(self);
}

JNIEXPORT jstring JNICALL Java_Foo_foo_bar(JNIEnv * env, jlong foo_ptr) {
  // Convert foo pointer from long.
  foo * self = (foo *)foo_ptr;
  // Create java string from bar c string.
  jstring jbar = (*env)->NewStringUTF(env, self->bar);
  // Return bar java string.
  return jbar;
}

. : , , .

+2

Python , Python . Py_INCREF() PyObject, JVM, Java. , , .

, , . - HashMap. , HashMap . JNI JVM, .

0

All Articles