Efficient data transfer from Java to C++ on windows

后端 未结 11 1234
我在风中等你
我在风中等你 2021-01-18 03:39

I\'m looking to stream lots of data (up to ~1 Gbit) from Java to a C++ application (both on the same machine). I\'m currently using a FIFO on Linux but need a Windows soluti

相关标签:
11条回答
  • 2021-01-18 04:10

    I recommend a UDP "connection" that acknowledges every Nth packet that was received without fault, and requests a retransmission of the few packets it will miss.

    0 讨论(0)
  • 2021-01-18 04:10

    I would advise against JNI, because it is very difficult to debug. If the C++ code segfaults or throws an uncaught exception, your JVM will crash, and you will have no idea why.

    0 讨论(0)
  • 2021-01-18 04:11

    If it's a big chunk of data in "one" function call I would recommend JNI.

    Take a look at this:Sharing output streams through a jni interface

    Snippet from the article, it transfert data from c++ to java, the opposite would be also easy to do:

    In all, the general strategy for sharing binary data (A/V files, images, etc.) from C with Java requires byte arrays. You create a Java byte array in C like this:

    const char[] rawData = {0,1,2,3,4,5,6,7,8,9}; //Or get some raw data from somewhere
    int dataSize = sizeof(rawData);
    printf("Building raw data array copy\n");
    jbyteArray rawDataCopy = env->NewByteArray(dataSize);
    env->SetByteArrayRegion(rawDataCopy, 0, dataSize, rawData);
    

    And pass it to Java like this:

    printf("Finding callback method\n");
    //Assumes obj is the Java instance that will receive the raw data via callback
    jmethodID aMethodId = env->GetMethodID(env->GetObjectClass(obj),"handleData","([B)V");
    if(0==aMethodId) throw MyRuntimeException("Method not found error");
    printf("Invoking the callback\n");
    env->CallVoidMethod(obj,aMethodId, &rawDataCopy);
    

    you would have a Java object that looked something like this:

    public class MyDataHandler {
      OutputStream dataStream;
      public MyDataHandler(OutputStream writeTo) { dataStream = writeTo;}
      public void handleData(byte[] incomingData) { dataStream.write(incomingData); }
    }
    

    That handler would be passed to C via native method like so:

    public class NativeIntegration {
      public native void generateBinaryWithHandler(MyDataHandler handler);
    
      //Here we assume response is something like a network stream
      public void doCallNativeFunction(ResponseStream response) {
        MyDataHandler handler = new MyDataHandler(response);
        generateBinaryWithHandler(handler);
      }
    }
    

    Also, you can use other technologies: CORBA, ASN.1 (ASN.1 tool), UDP or TCP

    0 讨论(0)
  • 2021-01-18 04:13

    If your C++ process starts the Java process, it might benefit from the inheritedChannel. Also, if the Java process is using a file, I recommend exploration of the transferTo and transferFrom methods. When doing file to file IO, these avoid needlessly tripping back and forth between user and kernel space; the same optimizations might kick in if you're using a special socket channel.

    0 讨论(0)
  • 2021-01-18 04:15

    If you're happy with writing JNI, consider Boost.Interprocess. This will give you portable shared memory on both Linux and Windows. Remember that there's no kernel roundtrip for reading/writing shared memory.

    0 讨论(0)
  • 2021-01-18 04:16

    I would use a local socket, which is, as you state, the most cross-platform method.

    Kernel-User space copies should not be an issue since any other method you could choose would requiere this kind of copy except for maybe shared memory. It is available on every Unix system and also Windows has its way of doing it

    To use shared memory in Java the only way is to implement it by means of your own .DLL/.SO and JNI to access it.

    0 讨论(0)
提交回复
热议问题