Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);

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

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

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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