1

Here is the native C++ method.

JNIEXPORT jboolean JNICALL Java_xpnp_XpNamedPipe_readBytes
(JNIEnv* pEnv, jclass cls, jlong pipeHandle, jbyteArray readBufferJava, jint bytestoread, jint timeoutMsecs){

    jbyte* readBuffer = NULL;
    try {
        readBuffer = pEnv->GetByteArrayElements(readBufferJava, NULL);
        if (readBuffer == NULL) {
            throw std::bad_alloc();
        }
        int retval = XPNP_readBytes ((XPNP_PipeHandle)pipeHandle, (char*)readBuffer, bytestoread, timeoutMsecs);

        std::cout<<"this is what I read: " << readBuffer << "\n";
        std::flush(std::cout);

        return (retval <= 0) ? 0 : retval;
    }catch (std::exception& except) {
        // setErrorInfo(except.what());
    }
    return 0;
}

This method prints the correct text of readBuffer that it reads from the call XPNP_readBytes, but passes an array of all zeros to Java! Any idea why that happens? Am I doing something wrong in passing the pointer or converting it to Java?

Here is the declaration of the native C++ method in the Java file.

private static native boolean readBytes(long pipeHandle, byte[] buffer, int bytesToRead, int timeoutMsecs);

This is where I'm calling the native method.

boolean b = readBytes(namedPipeHandle, buffer, bytesToRead, timeoutMsecs);
String a = new String(buffer);

The buffer I read after the call is all 0's, even though it prints the right text in the native code!

Rahul Jiresal
  • 1,006
  • 13
  • 24
  • 1
    I would consider using a direct ByteBuffer as this holds the address to a native block of memory. This avoids the need to copy the data to the byte[] and is more efficient if you need to read longer types such as `int` or `double` – Peter Lawrey Jul 14 '12 at 07:38
  • Oh all the `byte[]` that I used here are actually `ByteBuffer`s. I just did a `toArray()`. And for simplicity sake I just wrote `byte[]` in the post. Thanks for the tip anyway. – Rahul Jiresal Jul 14 '12 at 07:43
  • Basically `((DirectBuffer) byteBuffer).address()` is the address of a `void *` you can use. – Peter Lawrey Jul 14 '12 at 07:45
  • If they're direct buffers then see http://stackoverflow.com/questions/8000548/get-the-pointer-of-a-java-bytebuffer-though-jni/8002216#8002216 – Alan Stokes Jul 14 '12 at 10:48
  • This question and its comments are confusing. Problem is not reduced to its simplest version. "all the `byte[]` that I used here are actually `ByteBuffer`s" ... "If they're direct buffers then..." ... "No. They're byteArrays." Which is it? You say they are `ByteBuffer` then you say they are not. I came here because the question title suggested this question was about `ByteBuffer`, which I was looking up documentation for, but the question appears to not be about `ByteBuffer` at all, despite title saying it is. – Loduwijk Jun 16 '17 at 16:48
  • If this question is edited and improved so that it is consistent, I will remove down-vote. If it is made into a good question, I'll even up-vote. – Loduwijk Jun 16 '17 at 16:49

1 Answers1

1

Look up ReleaseByteArrayElements.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • I'm getting this error as soon as I return to Java from the native code. Maybe because of Releasing the memory? I have no clue what I'm doing here. `java(3440,0x1135d4000) malloc: *** error for object 0x7fdf6952d7f8: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug` – Rahul Jiresal Jul 14 '12 at 07:10
  • And sometimes it gives a different error. I get any of these two errors. Very randomly! `Invalid memory access of location 0x0 rip=0x1025fd6f7` – Rahul Jiresal Jul 14 '12 at 07:14
  • Sounds like you're writing outside the array's bounds. – Alan Stokes Jul 14 '12 at 10:50
  • What does your release call look like? Note that it is releasing your copy of the Java array's contents, not the Java array itself. – Alan Stokes Jul 14 '12 at 15:33
  • This is my release call. `pEnv->ReleaseByteArrayElements(readBufferJava, readBuffer, 0);` I thought the argument 0 copies back the content to `readBufferJava` and frees `readBuffer`, according to [this](http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html). – Rahul Jiresal Jul 14 '12 at 16:13
  • Yes, that's right. The release call isn't causing the problem. – Alan Stokes Jul 14 '12 at 16:17
  • My Java code doesn't stop at the breakpoint just after the native call. It crashes before that! That means the problem is in the native code. By the way, I'm on OS X Lion. – Rahul Jiresal Jul 14 '12 at 16:22
  • 1
    I would think you are writing more bytes into the array than will fit. You can use GetArrayLength to find out how big it is. Or otherwise corrupting memory. – Alan Stokes Jul 14 '12 at 16:32
  • Was allocating a few bytes less than what I was supposed to. Thanks a lot! – Rahul Jiresal Jul 14 '12 at 16:41
  • Even if this led OP to finding their needed fix, it is still not a good answer. It would have been a fine comment that someone could have ran with to make a good answer. Even more frustrating is that the question isn't about what its title says, making the abrupt answer even more frustrating. – Loduwijk Jun 16 '17 at 16:52
  • @Aaron Dude, this is a 3 year old question. Feel free to add a better answer; I will happily up-vote it (check out the Sportsmanship badge). Or indeed ask a better question. But sometimes you do someone a service by teaching them how to learn. – Alan Stokes Jun 16 '17 at 18:47
  • Sorry, I should have elaborated in my comment. Sometimes I think SO comment length restriction is a bad thing as it makes us terse. When I said "not a good answer," I meant that it does not provide any explanation and in general does not follow StackOverflow guidelines for what makes a good answer. Apologies if I was offensive, please forgive me. I was even more annoyed at the question itself than I was at your answer since question OP couldn't seem to make up their mind as to what the question was about, so if that tainted my comment at all, then apologies for that too. – Loduwijk Jun 16 '17 at 23:02
  • As for writing my own answer, I would not bother since doing so requires deciphering what exactly OP wants, which actually requires OP's acceptance of your answer to know for sure because of their mixed signals, and the root of the question is likely a duplicate anyway. Now that I think about it, same thing that stops me from wasting time answering should also lead me to be more understanding that you did not do more of an answer. With that in mind, I would undo my down-vote now if I could, but alas, it is locked in since more than 6 hours has passed. Sorry. Question still needs the -1 though. – Loduwijk Jun 16 '17 at 23:07