2010-01-04 15 views
7

que desea asignar algo de memoria en C y mantenerla asociada con una instancia de objeto de Java, así:Java JNI: ¿asociar recursos asignados en C con objetos java?

void configure(JNIEnv *object, jobject obj, ....) { 
    char *buf = new char[1024]; 
    // associated <buf> with <obj> somehow 
} 

Y luego libera la memoria cuando el objeto java se recoge la basura - que podía hacer esto llamando una función JNI del método finalize() del objeto java.

La pregunta es, ¿cómo asocio un puntero C con el objeto java? Mantener un largo campo en el objeto y emitir el puntero a largo? ¿Hay una mejor manera?

+2

dup: http://stackoverflow.com/questions/214699/jni-memory-management-using-the-invocation-api – falstro

+0

Más o menos, en esa pregunta no hay discusión sobre cómo asociar el objeto C al instancia de java. En el ejemplo presentado, el puntero se lanza a largo. ¿Es esta la única manera? – Viktor

Respuesta

16

Generalmente, si desea transferir un puntero de C a Java, se recomienda utilizar long para que haya suficientes bits para mantener el valor del puntero en caso de que la plataforma sea de 64 bits.

A continuación, echar un vistazo a ByteBuffer.allocateDirect() que crea una instancia de ByteBuffer el que la memoria puede ser compartida con C. Puede asignar una directa ByteBuffer tal desde el lado de Java, y pasarlo como un jobject a una función JNI y el interior de esta función JNI usa la función GetDirectBufferAddress.

Otra forma es envolver un área nativa de memoria con la función NewDirectByteBuffer JNI desde el lado nativo. Le da un jobject que vuelve al lado de Java (preste atención a las referencias locales y globales). Prestar atención al hecho de que una vez que la directa ByteBuffer que envuelve la memoria nativa ha sido creado, usted sigue siendo responsable de la gestión de la memoria nativa: en algún momento, tendrá que llamar a delete buf; en su código nativo, Java no lo hará para ti.

+0

Gracias! Si lo entiendo correctamente, el uso de ByteBuffer.allocateDirect() evita que el puntero pase + administración de la memoria; De esta forma, ByteBuffer administra la memoria. – Viktor

+1

Al asignar el ByteBuffer directo desde el lado de Java, deje que Java asigne el bloque de memoria, que se liberará cuando se ejecute 'finalize'. El único inconveniente es que no se sabe exactamente cuándo pasa el recolector de basura, por lo que no se sabe realmente cuándo se libera la memoria, que se va a liberar después de que haya terminado con el búfer. –

+0

+1 ¡Aseado! Buena respuesta. – JesperE

0

Java no tiene ningún concepto de puntero nativo, por lo que almacenarlo como un largo es la única opción real. Pero no debe confiar en finalize para liberar el puntero; el método de finalización no es confiable como un medio para limpiar los recursos. Ver this question para más detalles.

Cuestiones relacionadas