我想要实现以下操作:
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复制到每个字节缓冲区的直接地址中。我假设还有一些方法可以设置写入字节缓冲区的字节数,以便Java代码知道字节缓冲区的大小。在设置了字节缓冲区之后,我可以填充我的Java对象并返回它。与(i)和(ii)相比,这里创建了更多的字节缓冲区和Java对象,但避免了自定义协议的复杂性。在 (i)、(ii) 和 (iii) 之间进行选择的原因——考虑到我对这些缩略图所做的唯一操作是上传它们,我希望在通过 NIO 上传它们时用字节缓冲区(而不是字节数组)来保存额外副本。
(iv) 定义一个Java类,其中包含缩略图的字节数组数组(而不是字节缓冲区数组)和一个字节数组的感知哈希。我在本机代码中创建这些Java数组,并使用SetByteArrayRegion从我的GraphicsMagick blob复制字节。与先前的方法相比,缺点是现在在从堆复制此字节数组到某个直接缓冲区时,Java领域中会有另一个副本。不确定与 (iii) 相比,我是否会在复杂性方面节省任何东西。
任何建议都将非常棒。
编辑:@main提出了一个有趣的解决方案。我正在编辑我的问题以跟进该选项。如果我想像@main建议的那样包装本机内存,并使用 DirectBuffer,我如何知道何时可以安全地释放本机内存?