Каков «правильный» способ хранения нативного указателя внутри объекта Java? - PullRequest
24 голосов
/ 03 декабря 2008

Как правильно сохранить собственный указатель внутри объекта Java?

Я мог бы обращаться с указателем как с Java int, если случайно узнал, что собственные указатели имеют размер <= 32 бита, или с Java <code>long, если случайно узнал, что собственные указатели имеют размер <= 64 бит по размеру. Но есть ли лучший или более чистый способ сделать это? </p>

Редактировать : Возвращение собственного указателя из функции JNI - это именно то, что я не хочу сделать. Я бы предпочел вернуть объект Java, который представляет собственный ресурс. Однако объект Java, который я возвращаю, предположительно должен иметь поле, содержащее указатель, что возвращает меня к исходному вопросу.

Или, в качестве альтернативы, есть ли какой-нибудь лучший способ для функции JNI вернуть ссылку на собственный ресурс?

Ответы [ 6 ]

22 голосов
/ 03 декабря 2008

IIRC, java.util.zip и java.nio, просто используйте long.

3 голосов
/ 21 марта 2016

java.nio.DirectByteBuffer делает то, что вы хотите.

Внутренне он использует private long address для хранения значения указателя. Дах!

Используйте функцию JNI env->NewDirectByteBuffer((void*) data, sizeof(MyNativeStruct)), чтобы создать DirectByteBuffer на стороне C / C ++ и вернуть его на сторону Java в качестве ByteBuffer. Примечание: Ваша задача - освободить эти данные на родной стороне! В нем отсутствует автоматический очиститель, доступный в стандартном DirectBuffer.

На стороне Java вы можете создать DirectByteBuffer следующим образом:

ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);

Думайте, что-то вроде C malloc(sizeInBytes). Примечание: Имеет автоматический очиститель, который освобождает память, запрошенную ранее.

Но есть некоторые моменты, которые следует учитывать при использовании DirectByteBuffer:

  • Это может быть сборщик мусора (GC), если вы пропустите прямую ссылку на ByteBuffer.
  • Вы можете читать / записывать значения в заостренную структуру, но остерегайтесь как смещения, так и размера данных. Компилятор может добавить дополнительные пробелы для заполнения и нарушить ваши предполагаемые внутренние смещения в структуре. Структура с указателями (шаг 4 или 8 байт?) Также озадачивает ваши данные.
  • Direct ByteBuffers очень легко передать в качестве параметра для нативных методов, а также вернуть его в качестве возврата.
  • Вы должны привести к правильному типу указателя на стороне JNI. Тип по умолчанию, возвращаемый env->GetDirectBufferAddress(buffer), равен void*.
  • Вы не можете изменить значение указателя после его создания.
  • Ваша задача освободить память, ранее выделенную для буферов на нативной стороне. Те, которые вы использовали с env->NewDirectByteBuffer().
3 голосов
/ 03 декабря 2008

Хорошего пути нет. В SWT используется этот код:

int /*long*/ hModule = OS.GetLibraryHandle ();

и есть инструмент, который преобразует код между 32-битным и 64-битным путем перемещения комментария. Уродливо, но это работает. Все было бы намного проще, если бы Sun добавил объект «NativePointer» или что-то в этом роде, но они этого не сделали.

2 голосов
/ 03 декабря 2008

Я предполагаю, что это указатель, возвращенный из некоторого кода JNI, и мой совет будет , просто не делайте этого :)

В идеале код JNI должен передавать вам какую-то логическую ссылку на ресурс, а не фактический указатель?

Что касается вашего вопроса, то нет ничего, что приходило бы вам в голову по поводу более чистого способа хранения указателя - если вы знаете, что у вас есть, тогда используйте либо int, либо long, либо byte [], как требуется.

2 голосов
/ 03 декабря 2008

Лучшим способом было бы сохранить его в байтовом массиве, так как нативные указатели, во-первых, не очень Java-иш. int s и long s лучше резервировать для хранения числовых значений.

0 голосов
/ 03 декабря 2008

Вы можете посмотреть, как C # обрабатывает это с типом IntPtr. Создавая собственный тип для хранения указателей, можно использовать тот же тип, что и 32-разрядный или 64-разрядный, в зависимости от используемой системы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...