Каков наилучший способ доступа к памяти на Java, аналогичный mmap?

Я работаю над Java-приложением, которое должно взаимодействовать с приложением C. Приложение C использует разделяемую память и mmap для связи, и мне нужно, чтобы приложение Java имело доступ к той же самой памяти.

Моя первая попытка заключалась в использовании вызовов JNI для извлечения данных из общей памяти, но накладные расходы на каждый вызов JNI снизили производительность, поэтому я хотел бы получить доступ к этой памяти на Java и выполнить поиск данных на Java-сторона.

Идея, которую я имею, это то, что мне нужно будет сделать следующее:

  • Используйте один вызов JNI, чтобы получить местоположение разделяемой памяти, которое мне нужно прикрепить к
  • Создайте новый FileChannel()
  • Используйте этот FileChannel для создания MappedByteBuffer, используя map()

Это лучший способ сделать это? Кроме того, я не уверен, как создать FileChannel, чтобы указать на правильную ячейку памяти.

Ответ 1

Посмотрите на использование ByteBuffer.allocateDirect. По-видимому, эти буферы могут быть переданы через слой JNI на собственный код, который может напрямую обращаться к памяти.

См. эту страницу (цитируется ниже) для подсказок.

Теперь код JNI не только обнаруживает адрес собственного пространства памяти внутри буфера, созданного с помощью ByteBuffer.allocateDirect() на стороне Java, но он может выделять свою собственную память (например, с помощью malloc()) а затем перезвоните в JVM, чтобы обернуть это пространство памяти в новый объект ByteBuffer (для этого метод JNI - это NewDirectByteBuffer()).

Ответ 2

Я бы написал небольшой модуль C mmaps совместно используемую память и используемые сокеты, чтобы другое приложение могло видеть эту память (например, ваше приложение Java)

Ответ 3

Если у вас есть приложение C и Java, они могут просто общаться через консольные потоки - уродливые для двоичных данных, но это возможно. Я бы обменялся разделяемой памятью на другой стиль передачи сообщений - например. Пара сокетов TCP/IP.

Btw, какие данные передаются и насколько они велики?

Ответ 4

Нельзя ли написать Java-класс с некоторыми собственными методами, написать реализацию встроенного метода в C, чтобы делать то, что вы хотите, с помощью mmap. Затем скомпилируйте это в родную библиотеку и добавьте ее во время выполнения, используя LD_LIBRARY_PATH. Это позволит вам создавать собственные вызовы C на Java без накладных расходов JNI (я думаю).

Некоторые обучающие программы здесь: ссылка

Например, вы должны написать класс Java, например:

JMMap.java

public class JMMap {
    public native void write(...)
}

Затем запустите javah против файла класса, чтобы создать что-то вроде:

JMMap.h

JNIEXPORT void JNICALL Java_JMMap_write(JNIEnv *, jobject);

Внедрить это в .c файл. Скомпилируйте это в библиотеку. Добавьте его в LD-путь, а затем просто вызовите функцию Java.

Ответ 5

Если вы могли бы сохранить данные в файл на C, а затем получить доступ к файлу с Java, это было бы лучше. AFAIK вы не можете указывать на память так, как хотите использовать Java.