bytedeco / javacpp

The missing bridge between Java and native C++
Other
4.43k stars 576 forks source link

Inadequate Error Handling #734

Open seanrohead opened 6 months ago

seanrohead commented 6 months ago

I am using a library that uses JavaCPP. In the logs, I see the following error message:

Error getting method ID of java/lang/RuntimeException/<init>

This log message is created in the JavaCPP_getMethodID function in Generator.java:

  out.println("static JavaCPP_noinline jmethodID JavaCPP_getMethodID(JNIEnv* env, int i, const char* name, const char* sig) {");
  out.println("    jclass cls = JavaCPP_getClass(env, i);");
  out.println("    if (cls == NULL) {");
  out.println("        return NULL;");
  out.println("    }");
  out.println("    jmethodID mid = env->GetMethodID(cls, name, sig);");
  out.println("    if (mid == NULL || env->ExceptionCheck()) {");
  out.println("        JavaCPP_log(\"Error getting method ID of %s/%s\", JavaCPP_classNames[i], name);");
  out.println("        return NULL;");
  out.println("    }");
  out.println("    return mid;");
  out.println("}");

JavaCPP_getMethodID is called by JavaCPP_handleException:

  out.println("static JavaCPP_noinline jthrowable JavaCPP_handleException(JNIEnv* env, int i) {");
  out.println("    jstring str = NULL;");
  out.println("    try {");
  out.println("        throw;");
  out.println("    } catch (GENERIC_EXCEPTION_CLASS& e) {");
  out.println("        str = JavaCPP_createStringFromBytes(env, e.GENERIC_EXCEPTION_TOSTRING);");
  out.println("    } catch (...) {");
  out.println("        str = JavaCPP_createStringFromBytes(env, \"Unknown exception.\");");
  out.println("    }");
  out.println("    jmethodID mid = JavaCPP_getMethodID(env, i, \"<init>\", \"(Ljava/lang/String;)V\");");
  out.println("    if (mid == NULL) {");
  out.println("        return NULL;");
  out.println("    }");
  out.println("    return (jthrowable)env->NewObject(JavaCPP_getClass(env, i), mid, str);");
  out.println("}");

There are a few deficiencies here.

  1. Given that a RuntimeException cannot be created, the original exception message (i.e. str in JavaCPP_handleException) should be logged
  2. It's not clear from the logs whether the method could not be found because GetMethodID returned NULL or env->ExceptionCheck() returned true
  3. If env->ExceptionCheck() returns true, the pending exception should be retrieved and logged (ideally with env->ExceptionDescribe())
saudet commented 6 months ago

I'm guessing the bug is in your configuration or something, and this is an RFE?

If you have something concrete to propose, contributions are welcome!