Я хочу выделить некоторую память в C и сохранить связанным с экземпляром объекта Java, как это:
void configure(JNIEnv *object, jobject obj, ....) {
char *buf = new char[1024];
// associated <buf> with <obj> somehow
}
И затем позже свободный память, когда объект Java собран "мусор" - я мог сделать это путем вызывания функции JNI от завершения () метод объекта Java.
Вопрос, как я связываю указатель C с объектом Java? Сохраните длинное поле в объекте и бросьте указатель на долго? Существует ли лучший путь?
Обычно, если вы хотите перенести указатель с языка C на Java, рекомендуется использовать long
, чтобы было достаточно битов для хранения значения указателя, если платформа 64 бита.
Затем посмотрите на ByteBuffer.allocateDirect()
, который создает экземпляр ByteBuffer
, память которого можно совместно использовать с языком C. Вы можете выделить такой прямой ByteBuffer
со стороны Java, а затем передать его как jobject
в JNI функцию и внутри этой JNI функции использовать GetDirectBufferAddress
функцию.
Другой способ - обернуть исходную область памяти с помощью NewDirectByteBuffer
JNI функции с исходной стороны. Она дает вам jobject
, который вы передаете обратно на Java сторону (обратите внимание на локальные и глобальные ссылки). Обратите внимание на то, что после создания прямой ByteBuffer
, обёртывающей нативную память, вы всё равно отвечаете за управление нативной памятью: в какой-то момент вам придётся вызвать delete buf;
в вашем нативном коде, Java не будет делать этого за вас.
В Java нет понятия "нативный указатель", поэтому хранить его как длинный - единственный реальный вариант. Но для освобождения указателя не стоит полагаться на finalize
; метод finalize ненадежен как средство очистки ресурсов. См. этот вопрос для получения более подробной информации.