JNI Exception Handling (#1452)
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
#ifndef SHERPA_ONNX_JNI_COMMON_H_
|
#ifndef SHERPA_ONNX_JNI_COMMON_H_
|
||||||
#define SHERPA_ONNX_JNI_COMMON_H_
|
#define SHERPA_ONNX_JNI_COMMON_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#if __ANDROID_API__ >= 9
|
#if __ANDROID_API__ >= 9
|
||||||
#include <strstream>
|
#include <strstream>
|
||||||
|
|
||||||
@@ -42,4 +44,62 @@
|
|||||||
jobject NewInteger(JNIEnv *env, int32_t value);
|
jobject NewInteger(JNIEnv *env, int32_t value);
|
||||||
jobject NewFloat(JNIEnv *env, float 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_
|
#endif // SHERPA_ONNX_JNI_COMMON_H_
|
||||||
|
|||||||
@@ -353,11 +353,19 @@ Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_createStream(JNIEnv * /*env*/,
|
|||||||
|
|
||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_decode(
|
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_decode(
|
||||||
JNIEnv * /*env*/, jobject /*obj*/, jlong ptr, jlong 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;
|
||||||
|
}
|
||||||
|
|
||||||
auto recognizer = reinterpret_cast<sherpa_onnx::OfflineRecognizer *>(ptr);
|
auto recognizer = reinterpret_cast<sherpa_onnx::OfflineRecognizer *>(ptr);
|
||||||
auto stream = reinterpret_cast<sherpa_onnx::OfflineStream *>(streamPtr);
|
auto stream = reinterpret_cast<sherpa_onnx::OfflineStream *>(streamPtr);
|
||||||
|
|
||||||
recognizer->DecodeStream(stream);
|
recognizer->DecodeStream(stream);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromAsset(
|
|||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromFile(
|
JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromFile(
|
||||||
JNIEnv *env, jobject /*obj*/, jobject _config) {
|
JNIEnv *env, jobject /*obj*/, jobject _config) {
|
||||||
|
return SafeJNI(env, "OfflineTts_newFromFile", [&] -> jlong {
|
||||||
auto config = sherpa_onnx::GetOfflineTtsConfig(env, _config);
|
auto config = sherpa_onnx::GetOfflineTtsConfig(env, _config);
|
||||||
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
|
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
|
||||||
|
|
||||||
@@ -228,8 +229,8 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_OfflineTts_newFromFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto tts = new sherpa_onnx::OfflineTts(config);
|
auto tts = new sherpa_onnx::OfflineTts(config);
|
||||||
|
return reinterpret_cast<jlong>(tts);
|
||||||
return (jlong)tts;
|
}, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
|
|||||||
@@ -112,14 +112,20 @@ JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_delete(JNIEnv * /*env*/,
|
|||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_acceptWaveform(
|
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_acceptWaveform(
|
||||||
JNIEnv *env, jobject /*obj*/, jlong ptr, jfloatArray samples) {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||||
jfloat *p = env->GetFloatArrayElements(samples, nullptr);
|
jfloat *p = env->GetFloatArrayElements(samples, nullptr);
|
||||||
jsize n = env->GetArrayLength(samples);
|
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
|
SHERPA_ONNX_EXTERN_C
|
||||||
@@ -173,11 +179,17 @@ JNIEXPORT bool JNICALL Java_com_k2fsa_sherpa_onnx_Vad_isSpeechDetected(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_reset(JNIEnv * /*env*/,
|
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_Vad_reset(
|
||||||
jobject /*obj*/,
|
JNIEnv *env, jobject /*obj*/, jlong ptr) {
|
||||||
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);
|
auto model = reinterpret_cast<sherpa_onnx::VoiceActivityDetector *>(ptr);
|
||||||
model->Reset();
|
model->Reset();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SHERPA_ONNX_EXTERN_C
|
SHERPA_ONNX_EXTERN_C
|
||||||
|
|||||||
Reference in New Issue
Block a user