使用JNA从Java进行本机C调用的巨大内存占用

使用JNA从Java进行本机C调用的巨大内存占用,java,c,memory-management,jna,Java,C,Memory Management,Jna,我有一个本机C库,它在非常大的数据集上运行一些算法(大约数百mb到gb)。这是使用JNA从Java框架中调用的。Java加载数据并通过JNA将其传递到C库 问题是,似乎使用了过多的内存。对于一个数据集,在Java端完成所有加载后,该过程使用大约3.0gb,而C库使用2.0gb(通过内部内存管理确定)。但是,一旦调用了C库,这个过程的最大容量将达到9.5gb 具体问题,然后: Java和C端之间是否没有重叠?也就是说,JNA是否生成Java数据的C有效副本(顺便问一下,所有int和double数组

我有一个本机C库,它在非常大的数据集上运行一些算法(大约数百mb到gb)。这是使用JNA从Java框架中调用的。Java加载数据并通过JNA将其传递到C库

问题是,似乎使用了过多的内存。对于一个数据集,在Java端完成所有加载后,该过程使用大约3.0gb,而C库使用2.0gb(通过内部内存管理确定)。但是,一旦调用了C库,这个过程的最大容量将达到9.5gb

具体问题,然后:

Java和C端之间是否没有重叠?也就是说,JNA是否生成Java数据的C有效副本(顺便问一下,所有int和double数组)并将其传递给本机库,而不是传递给包含Java数据的相同块

即使假定没有重叠,并且本机库正在使用JVM中包含的数据的副本,那么额外的4.5gb从何而来?这大约是进程占用的系统内存量的两倍,我无法想象这一切会发生在哪里。关于JNA的这些方面的文档似乎非常有限,但我想知道是否有比我更熟悉JNA的人可能知道它为什么要使用这么多内存,以及我是否能够以及如何减少它的占用空间

编辑:启用JNA的Java类如下所示:

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指定的,以确保大小匹配。

如果只想在本机端分配内存,请使用JNA中的类并使用访问内存(内存有一个getByteBuffer()方法)。您可以将整数数组作为JNA指针传递给分配的内存。这将为您节省大量空间并提高性能。只需确保您在Java端管理本机内存资源。

听起来像是库中的一个bug,或者您不知道正在进行的内存分配,或者是JNA胶水中的一个bug。您是如何编写JNA绑定的?很难说没有看到任何代码…这基本上就是我所做的。在读取数据集时,我一直在犹豫是否在本机端分配这些内容并进行构建,因为我认为使用JNA会带来限制性的开销(我们有数千万条记录)。然而,使用JNA指针类,我分配了本机“对象”,然后在读取记录时传入记录。它并没有花费更多的时间,并且将内存使用量降低到了7.5g左右。这看起来还是很糟糕,但有25%的进步,所以我接受了。