0

I'm writing a JNI function that takes a ByteBuffer as parameter and writes some of its content to a (special) file under Linux. The code looks like this:

/*
 * Class:     myPackage_myClass
 * Method:    writeByteBuffer
 * Signature: (Ljava/nio/ByteBuffer;I)I
 */
JNIEXPORT jint JNICALL Java_myPackage_myClass_writeByteBuffer
  (JNIEnv *env, jobject thiz, jobject jBuffer, jint jLen)
{
  /* getting my file descriptor (fd) */
  const void* pointer = (void *) (*env)->GetDirectBufferAddress(env,(jobject)jBuffer);
  fprintf(stderr,"Address %p\n",pointer); //gives for example : "Address 0x7f58ac680640"
  int res = (int) write(fd, pointer,jLen);
  if(res < jLen) {
    throwErrnoExceptionError(env);
    return cleanup_running(ERR_NR);
  }
  return OK;
}

If I try to run it, it gives me an "invalid argument" error (errno 22).

However, the following code runs without problems:

/*
 * Class:     myPackage_myClass
 * Method:    writeByteBuffer
 * Signature: (Ljava/nio/ByteBuffer;I)I
 */
JNIEXPORT jint JNICALL Java_myPackage_myClass_writeByteBuffer
  (JNIEnv *env, jobject thiz, jobject jBuffer, jint jLen)
{
/* getting my file descriptor (fd) */
  char test[] = "Just some random text to test";
  int res = (int) write(fd, test,jLen);
  if(res < jLen) {
    throwErrnoExceptionError(env);
    return cleanup_running(ERR_NR);
  }
  return OK;
}

I checked, the buffer address is not NULL (I checked with a java debugger: The pointer corresponds to the address member of my ByteBuffer instance) and the buffers capacity is way bigger then jLen

Why does the call to write() does not work with my buffer, when it works using a directly allocated string?

ixolius
  • 202
  • 1
  • 11
  • 1
    You've left out the important part, replacing it by `/* error handling */`. Please don't post fake code. – R.. GitHub STOP HELPING ICE Feb 04 '21 at 19:50
  • The `errno` is [probably] coming from the `write` syscall. It doesn't like the address that has been passed. Try: `void *adr = (*env)->GetDirectBufferAddress(env,(jobject)jBuffer); printf("%p\n",adr); write(fd,adr,jLen);` I bet `adr` will be "funny". See: https://stackoverflow.com/questions/29745584/using-getdirectbufferaddress-from-jni implies that you get back "big endian" instead of "little endian" – Craig Estey Feb 04 '21 at 19:54
  • @R..GitHubSTOPHELPINGICE I don't have full rights to post all code that I want, that is why I redacted it a bit. Please tell me, if you still miss something relevant and why. – ixolius Feb 04 '21 at 21:10
  • @CraigEstey Given the fact that I am on byte level, how can endianess matter here? – ixolius Feb 04 '21 at 21:13
  • It explains that in the link. So, when you did the `printf` as I suggested, what did you get? – Craig Estey Feb 04 '21 at 21:17
  • @CraigEstey Nothing in that link implies that the address itself is big-endian. But he should certainly error-check his `GetDirectBufferAddress()` call. Could be zero for example, if it isn't really a direct byte buffer. Why he is casting a `jobject` to `jobject` is another mystery. – user207421 Feb 04 '21 at 22:58
  • @user207421 Ah, I misread malat's answer in the link to imply the address was coming back big endian vs. the buffer contents. As to [this] OP's issue, it could be _any_ arg to `write`. But, since OP's [simplified] working version uses [only] a different pointer, that tends to point to the buffer address [vs. fd or len]. Either it's out-of-range [or NULL]. – Craig Estey Feb 04 '21 at 23:06
  • @CraigEstey I updated my code, so you can see the Address. I ran it using a java debugger and found out that it is the same address as the base address of my ByteBuffer (in decimal notation) – ixolius Feb 05 '21 at 08:18

0 Answers0