【发布时间】:2013-07-16 13:29:39
【问题描述】:
我正在努力实现以下目标:
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) 背后的基本原理 - 鉴于我对这些缩略图所做的唯一事情就是上传它们,我希望在通过 NIO 上传它们时保存一个带有字节缓冲区(与字节数组)的额外副本.
(iv) 定义一个 Java 类,该类具有用于缩略图的字节数组(而不是字节缓冲区)和用于感知散列的字节数组。我在本机代码中创建这些 Java 数组,并使用 SetByteArrayRegion 从我的 GraphicsMagick blob 中复制字节。与以前的方法相比,缺点是现在在上传时将此字节数组从堆复制到某个直接缓冲区时,Java 领域中还会有另一个副本。不确定我是否会在复杂性方面节省任何东西与 (iii) 在这里。
任何建议都会很棒。
编辑:@main 提出了一个有趣的解决方案。我正在编辑我的问题以跟进该选项。如果我想像@main 建议的那样将本机内存包装在 DirectBuffer 中,我怎么知道何时可以安全地释放本机内存?
【问题讨论】:
-
你能用更简短的形式表达你的问题吗?
-
为什么不尝试使用看起来足够快的最简单方法呢?如果速度不够快,或者你很好奇,你可以尝试更复杂的东西并进行比较。从您想到的所有方法和考虑的权衡来看,you know more about this specific problem and will be better able to answer it than anyone else。
-
@Alex 我想提供尽可能多的细节,因为问题都是关于细节的。
-
@andrewdotn 我试图验证我的假设的正确性,除了找出什么会很快。这在最初的问题中可能并不明显,因为我一直在谈论性能权衡。
标签: java java-native-interface graphicsmagick