diff --git a/java/src/main/java/ai/onnxruntime/OrtSession.java b/java/src/main/java/ai/onnxruntime/OrtSession.java index 2fae9af4ec..df6f27741f 100644 --- a/java/src/main/java/ai/onnxruntime/OrtSession.java +++ b/java/src/main/java/ai/onnxruntime/OrtSession.java @@ -1001,8 +1001,11 @@ public class OrtSession implements AutoCloseable { } /** - * Adds Xnnpack as an execution backend. Needs to list all options here if a new option - * supported. current supported options: {} + * Adds Xnnpack as an execution backend. Needs to list all options hereif a new option + * supported. current supported options: {} The maximum number of provider options is set to 128 + * (see addExecutionProvider's comment). This number is controlled by + * ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH in ai_onnxruntime_OrtSession_SessionOptions.c. If 128 is + * not enough, please increase it or implementing an incremental way to add more options. * * @param providerOptions options pass to XNNPACK EP for initialization. * @throws OrtException If there was an error in native code. @@ -1132,6 +1135,10 @@ public class OrtSession implements AutoCloseable { private native void addCoreML(long apiHandle, long nativeHandle, int coreMLFlags) throws OrtException; + /* + * The max length of providerOptionKey and providerOptionVal is 128, as specified by + * ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH (search ONNXRuntime PR #14067 for its location). + */ private native void addExecutionProvider( long apiHandle, long nativeHandle, diff --git a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c index ed01b54f8a..1e00a05437 100644 --- a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c +++ b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c @@ -15,6 +15,7 @@ #endif // Providers +#define ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH 128 #include "onnxruntime/core/providers/cpu/cpu_provider_factory.h" #include "onnxruntime/core/providers/dnnl/dnnl_provider_factory.h" #include "onnxruntime/core/providers/nnapi/nnapi_provider_factory.h" @@ -631,29 +632,33 @@ JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExe const char* epName = (*jniEnv)->GetStringUTFChars(jniEnv, jepName, NULL); const OrtApi* api = (const OrtApi*)apiHandle; OrtSessionOptions* options = (OrtSessionOptions*)optionsHandle; - int keyCount = (*jniEnv)->GetArrayLength(jniEnv, configKeyArr); + size_t keyCount = (*jniEnv)->GetArrayLength(jniEnv, configKeyArr); - const char** keyArray = (const char**)malloc(keyCount * sizeof(const char*)); - const char** valueArray = (const char**)malloc(keyCount * sizeof(const char*)); - jstring* jkeyArray = (jstring*)malloc(keyCount * sizeof(jstring)); - jstring* jvalueArray = (jstring*)malloc(keyCount * sizeof(jstring)); + if (keyCount > ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH) { + throwOrtException(jniEnv, ORT_INVALID_ARGUMENT, "Too many provider options."); + } - for (int i = 0; i < keyCount; i++) { - jkeyArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configKeyArr, i)); - jvalueArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configValueArr, i)); + const char* keyArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + const char* valueArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + jstring jkeyArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + jstring jvalueArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + + for (size_t i = 0; i < keyCount; i++) { + // In this loop, it is type-safe to call (jsize)i since i is + // upper-bounded by keyCount (type: jsize) returned by GetArrayLength. + jkeyArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configKeyArr, (jsize)i)); + jvalueArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configValueArr, (jsize)i)); keyArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jkeyArray[i], NULL); valueArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jvalueArray[i], NULL); } checkOrtStatus(jniEnv, api, api->SessionOptionsAppendExecutionProvider(options, epName, keyArray, valueArray, keyCount)); - for (int i = 0; i < keyCount; i++) { + for (size_t i = 0; i < keyCount; i++) { (*jniEnv)->ReleaseStringUTFChars(jniEnv, jkeyArray[i], keyArray[i]); (*jniEnv)->ReleaseStringUTFChars(jniEnv, jvalueArray[i], valueArray[i]); } (*jniEnv)->ReleaseStringUTFChars(jniEnv, jepName, epName); - free((void*)keyArray); - free((void*)valueArray); - free((void*)jkeyArray); - free((void*)jvalueArray); } + +#undef ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH