Огромный объем памяти, делающий нативные C-вызовы из Java с использованием JNA - PullRequest
2 голосов
/ 22 августа 2011

У меня есть собственная библиотека C, которая запускает некоторые алгоритмы для очень больших наборов данных (порядка сотен мегабайт в гб).Это вызывается из среды Java с использованием JNA.Java загружает данные и передает их через JNA в библиотеку C.

Проблема в том, что, похоже, используется чрезмерное количество памяти.Для одного набора данных процесс использует около 3,0 ГБ после завершения загрузки на стороне Java, а 2,0 ГБ используется библиотекой C (как определено с помощью внутреннего управления памятью).Но процесс, как только вызывается библиотека C, заканчивается с максимальным значением около 9,5 ГБ!

Конкретные вопросы, затем:

Нет ли совпадений между стороной Java и C?То есть, создает ли JNA C-валидную копию данных Java (кстати, все массивы int и double) и передает ее в собственную библиотеку вместо тех же блоков, которые содержат данные в Java?

Даже если предположить, что нет совпадений, и нативная библиотека использует копию данных, содержащихся в JVM, откуда эти дополнительные 4,5 ГБ?Это примерно вдвое увеличивает объем системной памяти, занятой процессом, и я не могу себе представить, где все это происходит.Документация по этим аспектам JNA кажется очень ограниченной, но мне интересно, мог бы кто-нибудь, кто знаком с JNA лучше, чем я, знает, почему он использует так много памяти, и если и как я смогу уменьшить его площадь.

РЕДАКТИРОВАТЬ: Java-класс с поддержкой JNA выглядит следующим образом:

public interface MyNativeLibrary extends Library {

    MyNativeLibrary INSTANCE = (MyNativeLibrary) Native.loadLibrary(
            "native_library", MyNativeLibrary.class);

    int native_library_function(int num_inputs, int inputs[], int max_num_outputs, int preallocated_outputs[]);

}

В этом случае возвращаемым значением встроенной функции будет число возвращенных выходных данных или код ошибки.Интерфейс C указывается с int32_t, чтобы убедиться, что размеры совпадают.

1 Ответ

1 голос
/ 23 августа 2011

Если вы хотите выделить память только на собственной стороне, используйте класс Memory в JNA и получите доступ к памяти, используя java.nio.ByteBuffer (в памяти есть getByteBuffer ()метод).Вы можете передавать свои массивы целых чисел, поскольку JNA Указывает на выделенную память.Это должно сэкономить вам немного места и улучшить производительность.Просто убедитесь, что вы управляете собственными ресурсами памяти на стороне Java.

...