我正在努力实现以下目标:
1)我在java端有一个代表图像的字节数组。
2)我需要让我的本机代码访问它。
3) 本机代码使用 GraphicsMagick 解码此图像并通过调用 resize 创建一堆缩略图。它还计算图像的感知散列,可以是向量或 unint8_t 数组。
4) 一旦我将此数据返回到 Java 端,不同的线程将读取它。缩略图将通过 HTTP 上传到一些外部存储服务。
我的问题是:
1)将字节从Java传递到我的本机代码的最有效方法是什么?我可以作为字节数组访问它。我认为将其作为字节缓冲区(包装此字节数组)与此处的字节数组相比没有任何特别的优势。
2) 将这些缩略图和感知散列返回到 java 代码的最佳方法是什么?我想到了几个选择:
(i) 我可以在 Java 中分配一个字节缓冲区,然后将它传递给我的本机方法。然后,本机方法可以写入它并在完成后设置一个限制,并返回写入的字节数或一些指示成功的布尔值。然后,我可以对字节缓冲区进行切片和切块,以提取不同的缩略图和感知散列,并将其传递给将上传缩略图的不同线程。这种方法的问题是我不知道要分配什么大小。所需的大小将取决于生成的缩略图的大小,我事先不知道和缩略图的数量(我事先知道这一点)。
(ii) 一旦我知道所需的大小,我也可以在本机代码中分配字节缓冲区。我可以根据我的自定义打包协议将我的 blob 存储到正确的区域并返回这个字节缓冲区。(i) 和 (ii) 看起来都很复杂,因为自定义打包协议必须指示每个缩略图的长度和感知散列。
(iii) 定义一个具有缩略图字段的 Java 类:字节缓冲区数组和感知散列:字节数组。当我知道所需的确切大小时,我可以在本机代码中分配字节缓冲区。然后我可以将 GraphicsMagick blob 中的字节 memcpy 到每个字节缓冲区的直接地址。我假设还有一些方法可以设置写入字节缓冲区的字节数,以便 java 代码知道字节缓冲区有多大。设置字节缓冲区后,我可以填写我的 Java 对象并返回它。与 (i) 和 (ii) 相比,我在这里创建了更多字节缓冲区以及 Java 对象,但我避免了自定义协议的复杂性。(i)、(ii) 和 (iii) 背后的基本原理 - 鉴于我对这些缩略图所做的唯一事情就是上传它们,
(iv) 定义一个 Java 类,该类具有用于缩略图的字节数组(而不是字节缓冲区)和用于感知散列的字节数组。我在本机代码中创建这些 Java 数组,并使用 SetByteArrayRegion 从我的 GraphicsMagick blob 中复制字节。与以前的方法相比,缺点是现在在上传时将此字节数组从堆复制到某个直接缓冲区时,Java 领域中还会有另一个副本。不确定我是否会在复杂性方面与(iii)在这里保存任何东西。
任何建议都会很棒。
编辑:@main 提出了一个有趣的解决方案。我正在编辑我的问题以跟进该选项。如果我想像@main 建议的那样将本机内存包装在 DirectBuffer 中,我怎么知道何时可以安全地释放本机内存?