Jni code leads to EXC_BAD_ACCESS

Hello! I have a problem
GL.java:

@Runtime(CRuntime.class)
public final class GL {

  static {
    NatJ.register();
  }

  public static native void glTexImage2D(
      int target,
      int level,
      int internalFormat,
      int width, int height,
      int border,
      int format,
      int type,
      byte data[]);
}

GL.cpp:

JNIEXPORT void JNICALL Java_delightex_opengl_GL_glTexImage2D(JNIEnv *env, jclass, jint target, jint level, jint internalFormat, jint width, jint height, jint border, jint format, jint type, jbyteArray data) {
   if (data == NULL) {
     glTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
     return;
   }
   void *dataPtr = env->GetPrimitiveArrayCritical(data, 0);
   glTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
   env->ReleasePrimitiveArrayCritical(data, dataPtr, JNI_COMMIT);
}

And when I call glTexImage2D in my code then it lead to crash application with EXC_BAD_ACCESS. Actually in some cases it works well, in some failed. I see reason(EXC_BAD_ACCESS) when I start my project in xcode.
When I use gradle task or Intellij plugin app just silently crashes without logs.
So, How can I understand what’s wrong with my code?

Dear Zufar,

If you are using standard JNI, then you should not specify NatJ annotations and the NatJ.register() block on the class. Could you please try it without the annotations and the register block?

Best Regards,
Gergely

actually I use one cpp file and one java file for all jni functions and natj-annotated functions. Should I split it to two different java-files?

Dear zufarfakhurtdinov,

could you please send the stacktrace shown from Xcode when you get EXC_BAD_ACCESS?


but there is no useful information. App just hangs on

__lldb_unnamed_function296$$AGXGLDriver and GL_glTexImage2D

Dear zufarfakhurtdinov,

could you please create a screenshot of your debug navigator area in the crashed state? it should look something like this:

Dear zufarfakhurtdinov,

from this I think that your JNI usage is correct, but the issue is from the parameters being incorrect, causing an OpenGL crash. This can be easily caused by “data” having less bytes than OpenGL wants to read and reading outside of the byte array’s memory region will cause an EXC_BAD_ACCESS.

If I use natj wrapped function glTexImage2D with copying data

  public static void glTexImage2D(
      int target,
      int level,
      int internalFormat,
      int width, int height,
      int border,
      int format,
      int type,
      byte data[]) {
    long ptr = data == null ? 0 : PtrFactory.newByteArray(data).getPeer().getPeer();
    glTexImage2D(target, level, internalFormat, width, height, border, format, type, ptr);
  }
  @CFunction
  public static native void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int   format, int type, /*@Pointer*/ long data);

Its works. But what the reason? These versions should do mostly the same.

Dear Zufar,

I think there is a typo in your JNI function.

This line:

should read (dataPtr instead of data):

glTexImage2D(target, level, internalFormat, width, height, border, format, type, dataPtr);

Best Regards,
Gergely

Thank you very much! Sorry for stupid reason question)

No problem, such typos happen to all of us. :slight_smile: