JNI Exception Handling (#1452)
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
#ifndef SHERPA_ONNX_JNI_COMMON_H_
|
||||
#define SHERPA_ONNX_JNI_COMMON_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#if __ANDROID_API__ >= 9
|
||||
#include <strstream>
|
||||
|
||||
@@ -42,4 +44,62 @@
|
||||
jobject NewInteger(JNIEnv *env, int32_t value);
|
||||
jobject NewFloat(JNIEnv *env, float value);
|
||||
|
||||
// Template function for non-void return types
|
||||
template <typename Func, typename ReturnType>
|
||||
ReturnType SafeJNI(JNIEnv *env, const char *functionName, Func func,
|
||||
ReturnType defaultValue) {
|
||||
try {
|
||||
return func();
|
||||
} catch (const std::exception &e) {
|
||||
jclass exClass = env->FindClass("java/lang/RuntimeException");
|
||||
if (exClass != nullptr) {
|
||||
std::string errorMessage = std::string(functionName) + ": " + e.what();
|
||||
env->ThrowNew(exClass, errorMessage.c_str());
|
||||
}
|
||||
} catch (...) {
|
||||
jclass exClass = env->FindClass("java/lang/RuntimeException");
|
||||
if (exClass != nullptr) {
|
||||
std::string errorMessage = std::string(functionName) +
|
||||
": Native exception: caught unknown exception";
|
||||
env->ThrowNew(exClass, errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Specialization for void return type
|
||||
template <typename Func>
|
||||
void SafeJNI(JNIEnv *env, const char *functionName, Func func) {
|
||||
try {
|
||||
func();
|
||||
} catch (const std::exception &e) {
|
||||
jclass exClass = env->FindClass("java/lang/RuntimeException");
|
||||
if (exClass != nullptr) {
|
||||
std::string errorMessage = std::string(functionName) + ": " + e.what();
|
||||
env->ThrowNew(exClass, errorMessage.c_str());
|
||||
}
|
||||
} catch (...) {
|
||||
jclass exClass = env->FindClass("java/lang/RuntimeException");
|
||||
if (exClass != nullptr) {
|
||||
std::string errorMessage = std::string(functionName) +
|
||||
": Native exception: caught unknown exception";
|
||||
env->ThrowNew(exClass, errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to validate JNI pointers
|
||||
inline bool ValidatePointer(JNIEnv *env, jlong ptr,
|
||||
const char *functionName, const char *message) {
|
||||
if (ptr == 0) {
|
||||
jclass exClass = env->FindClass("java/lang/NullPointerException");
|
||||
if (exClass != nullptr) {
|
||||
std::string errorMessage = std::string(functionName) + ": " + message;
|
||||
env->ThrowNew(exClass, errorMessage.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SHERPA_ONNX_JNI_COMMON_H_
|
||||
|
||||
@@ -353,11 +353,19 @@ Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_createStream(JNIEnv * /*env*/,
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_decode(
|
||||
JNIEnv * /*env*/, jobject /*obj*/, jlong ptr, jlong streamPtr) {
|
||||
auto recognizer = reinterpret_cast<sherpa_onnx::OfflineRecognizer *>(ptr);
|
||||
auto stream = reinterpret_cast<sherpa_onnx::OfflineStream *>(streamPtr);
|
||||
JNIEnv *env, jobject /*obj*/, jlong ptr, jlong streamPtr) {
|
||||
SafeJNI(env, "OfflineRecognizer_decode", [&] {
|
||||
if (!ValidatePointer(env, ptr, "OfflineRecognizer_decode",
|
||||
"OfflineRecognizer pointer is null.") ||
|
||||
!ValidatePointer(env, streamPtr, "OfflineRecognizer_decode",
|
||||
"OfflineStream pointer is null.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
recognizer->DecodeStream(stream);
|
||||
auto recognizer = reinterpret_cast<sherpa_onnx::OfflineRecognizer *>(ptr);
|
||||
auto stream = reinterpret_cast<sherpa_onnx::OfflineStream *>(streamPtr);
|
||||
recognizer->DecodeStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
|
||||
@@ -220,16 +220,17 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromAsset(
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromFile(
|
||||
JNIEnv *env, jobject /*obj*/, jobject _config) {
|
||||
auto config = sherpa_onnx::GetOfflineTtsConfig(env, _config);
|
||||
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
|
||||
return SafeJNI(env, "OfflineTts_newFromFile", [&] -> jlong {
|
||||
auto config = sherpa_onnx::GetOfflineTtsConfig(env, _config);
|
||||
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
|
||||
|
||||
if (!config.Validate()) {
|
||||
SHERPA_ONNX_LOGE("Errors found in config!");
|
||||
}
|
||||
if (!config.Validate()) {
|
||||
SHERPA_ONNX_LOGE("Errors found in config!");
|
||||
}
|
||||
|
||||
auto tts = new sherpa_onnx::OfflineTts(config);
|
||||
|
||||
return (jlong)tts;
|
||||
auto tts = new sherpa_onnx::OfflineTts(config);
|
||||
return reinterpret_cast<jlong>(tts);
|
||||
}, 0L);
|
||||
}
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
|
||||
@@ -112,14 +112,20 @@ JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_delete(JNIEnv * /*env*/,
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_acceptWaveform(
|
||||
JNIEnv *env, jobject /*obj*/, jlong ptr, jfloatArray samples) {
|
||||
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||
SafeJNI(env, "Vad_acceptWaveform", [&] {
|
||||
if (!ValidatePointer(env, ptr, "Vad_acceptWaveform",
|
||||
"VoiceActivityDetector pointer is null.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
jfloat *p = env->GetFloatArrayElements(samples, nullptr);
|
||||
jsize n = env->GetArrayLength(samples);
|
||||
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||
jfloat *p = env->GetFloatArrayElements(samples, nullptr);
|
||||
jsize n = env->GetArrayLength(samples);
|
||||
|
||||
model->AcceptWaveform(p, n);
|
||||
model->AcceptWaveform(p, n);
|
||||
|
||||
env->ReleaseFloatArrayElements(samples, p, JNI_ABORT);
|
||||
env->ReleaseFloatArrayElements(samples, p, JNI_ABORT);
|
||||
});
|
||||
}
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
@@ -173,11 +179,17 @@ JNIEXPORT bool JNICALL Java_com_k2fsa_sherpa_onnx_Vad_isSpeechDetected(
|
||||
}
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_reset(JNIEnv * /*env*/,
|
||||
jobject /*obj*/,
|
||||
jlong ptr) {
|
||||
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||
model->Reset();
|
||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_reset(
|
||||
JNIEnv *env, jobject /*obj*/, jlong ptr) {
|
||||
SafeJNI(env, "Vad_reset", [&] {
|
||||
if (!ValidatePointer(env, ptr, "Vad_reset",
|
||||
"VoiceActivityDetector pointer is null.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||
model->Reset();
|
||||
});
|
||||
}
|
||||
|
||||
SHERPA_ONNX_EXTERN_C
|
||||
|
||||
Reference in New Issue
Block a user