如何避免在 Java 和本机 C++ 代码之间复制数据
How to avoid copying data between Java and Native C++ Code
我正在编写 C++ 库,不同的 Android 应用程序将使用它来处理某种组织的数据,如二维存储,其中每个维度都没有预定义的大小限制(如浮点数组的数组, 数组的大小可能会很大)。
当前解决方案使用 SWIG 将数据从 Java 代码分配的内存复制到 C++ 结构。事实证明,每个浮点值数组(在 Java 中)都变成了浮点向量(在 C++ 中)。
问题是大量数据的重复会增加 运行 可用内存不足的风险。我明白,在任何情况下,内存消耗问题都应该通过输入量限制来解决,但是库不知道有多少内存可用并且应该有完整的数据(需要重复访问任何数据元素)来执行正确的处理。
所以现在我正在考虑为 Java 和 C++ 使用一个数据存储的可能性,因此 C++ 代码需要直接访问 Java 代码存储的数据到 Java 上分配的内存side(不考虑将C++代码分配的内存作为单一存储)。
我想知道如何以安全的方式组织此类内存共享(最好使用 SWIG)。
我觉得这样的实现可能会有一些困难,例如使用 Java 垃圾收集器(C++ 代码可以寻址到已经解除分配的存储)并通过包装器减慢内存访问(如前所述,库需要重复访问每个数据项)……但也许有人建议我一个可靠的解决方案.
如果有充分和令人信服的论据支持,我的想法为什么错误的解释可以被接受。
您可以使用 Critical Native 实现来访问 raw 数据数组。此技术允许 直接访问 jvm 内存 而无需在 Java 和本机代码之间传输数据。
但这还有下一个限制:
- 必须是静态的,不能同步;
- 参数类型必须是基本类型或基本数组;
- 实现不能调用 JNI 函数,即它不能分配 Java 个对象或抛出异常;
- 不应该运行很长时间,因为它会在 运行ning 时阻塞 GC。
critical native 的声明看起来像一个常规的 JNI 方法,除了:
- 它以
JavaCritical_
开头,而不是 Java_
;
- 它没有额外的
JNIEnv*
和 jclass
参数;
- Java 数组传入两个参数:第一个是数组长度,第二个是指向原始数组数据的指针。也就是不用调用
GetArrayElements
和朋友,直接用一个数组指针就可以瞬间
查看 and source article了解详情。
我正在编写 C++ 库,不同的 Android 应用程序将使用它来处理某种组织的数据,如二维存储,其中每个维度都没有预定义的大小限制(如浮点数组的数组, 数组的大小可能会很大)。
当前解决方案使用 SWIG 将数据从 Java 代码分配的内存复制到 C++ 结构。事实证明,每个浮点值数组(在 Java 中)都变成了浮点向量(在 C++ 中)。
问题是大量数据的重复会增加 运行 可用内存不足的风险。我明白,在任何情况下,内存消耗问题都应该通过输入量限制来解决,但是库不知道有多少内存可用并且应该有完整的数据(需要重复访问任何数据元素)来执行正确的处理。
所以现在我正在考虑为 Java 和 C++ 使用一个数据存储的可能性,因此 C++ 代码需要直接访问 Java 代码存储的数据到 Java 上分配的内存side(不考虑将C++代码分配的内存作为单一存储)。
我想知道如何以安全的方式组织此类内存共享(最好使用 SWIG)。
我觉得这样的实现可能会有一些困难,例如使用 Java 垃圾收集器(C++ 代码可以寻址到已经解除分配的存储)并通过包装器减慢内存访问(如前所述,库需要重复访问每个数据项)……但也许有人建议我一个可靠的解决方案. 如果有充分和令人信服的论据支持,我的想法为什么错误的解释可以被接受。
您可以使用 Critical Native 实现来访问 raw 数据数组。此技术允许 直接访问 jvm 内存 而无需在 Java 和本机代码之间传输数据。
但这还有下一个限制:
- 必须是静态的,不能同步;
- 参数类型必须是基本类型或基本数组;
- 实现不能调用 JNI 函数,即它不能分配 Java 个对象或抛出异常;
- 不应该运行很长时间,因为它会在 运行ning 时阻塞 GC。
critical native 的声明看起来像一个常规的 JNI 方法,除了:
- 它以
JavaCritical_
开头,而不是Java_
; - 它没有额外的
JNIEnv*
和jclass
参数; - Java 数组传入两个参数:第一个是数组长度,第二个是指向原始数组数据的指针。也就是不用调用
GetArrayElements
和朋友,直接用一个数组指针就可以瞬间
查看