【问题标题】:How to upload Direct Buffer gotten from JNI to S3 directly如何将从JNI获取的Direct Buffer直接上传到S3
【发布时间】:2022-11-26 17:07:40
【问题描述】:

我创建了一个共享内存(大小为 200MB),它映射到系统上运行的 Java 进程和 C++ 进程。 C++ 进程在这个共享内存中写入 50MB 的数据。在 JAVA 端,映射相同共享内存的 JNI 函数将此数据读入直接缓冲区,如下所示:

JNIEXPORT jobject JNICALL Java_service_SharedMemoryJNIService_getDirectByteBuffer
  (JNIEnv *env, jclass jobject, jlong buf_addr, jint buf_len){

        return env->NewDirectByteBuffer((void *)buf_addr, buf_len);

  }

现在,在 JAVA 端,我需要将这 50MB 的数据上传到 S3。目前,我必须像这样将这个直接缓冲区复制到 JVM 堆中的缓冲区:

public String uploadByteBuffer(String container, String objectKey, ByteBuffer bb) {

            BlobStoreContext context = getBlobStoreContext();
            BlobStore blobStore = context.getBlobStore();
            byte[] buf = new byte[bb.capacity()];
            bb.get(buf);
            ByteArrayPayload payload = new ByteArrayPayload(buf);
            Blob blob = blobStore.blobBuilder(objectKey)
                    .payload(payload)
                    .contentLength(bb.capacity())
                    .build();
            blobStore.putBlob(container, blob);
            return objectKey;
}

我想避免这种从共享内存到 JVM 堆的额外复制。有没有办法直接将直接缓冲区中包含的数据上传到 S3?

谢谢

【问题讨论】:

    标签: java amazon-s3 java-native-interface jclouds


    【解决方案1】:

    BlobBuilder.payload 可以使用 ByteSource 并且您可以使用 ByteBuffer 包装器:

    public class ByteBufferByteSource extends ByteSource {
       private final ByteBuffer buffer;
    
       public ByteBufferByteSource(ByteBuffer buffer) {
          this.buffer = checkNotNull(buffer);
       }
    
       @Override
       public InputStream openStream() {
          return new ByteBufferInputStream(buffer);
       }
    
       private static final class ByteBufferInputStream extends InputStream {
          private final ByteBuffer buffer;
          private boolean closed = false;
    
          ByteBufferInputStream(ByteBuffer buffer) {
             this.buffer = buffer;
          }
    
          @Override
          public synchronized int read() throws IOException {
             if (closed) {
                throw new IOException("Stream already closed");
             }
             try {
                return buffer.get();
             } catch (BufferUnderflowException bue) {
                return -1;
             }
          }
    
          @Override
          public void close() throws IOException {
             super.close();
             closed = true;
          }
       }
    }
    

    您将需要覆盖 read(byte[], int, int) 以提高效率。我还向 jclouds 提出了这个 pull request:https://github.com/apache/jclouds/pull/158 你可以改进。

    【讨论】:

      猜你喜欢
      • 2021-04-02
      • 2012-03-14
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 2015-04-12
      • 1970-01-01
      • 2019-01-11
      • 2011-06-06
      相关资源
      最近更新 更多