所以我为Microsoft Sapi 5.4创建了一个JNI-C ++ dll。程序顺利执行。
但即使我在java程序的主程序中调用System.exit(int)
,该程序仍然在运行。我正在使用netbeans进行java编码。此外,永远不会调用Runtime.getRuntime().addShutdownHook()
。
任何指针为什么会这种情况继续发生。
更新:问题不在于shutdownhook。只要指针为delete
,就会出现问题。每当deleteTTS和析构函数调用delete
函数时,本机端就会一直挂起。
代码段:
JavaVM * javaVM;
jobject javaObj;
//different java callback variables
long speechObjId;
std::wstring theString(L"");
bool debug;
CRESpeechLib::CRESpeechLib(){
init(1);
}
CRESpeechLib::CRESpeechLib(int val){
init(val);
}
CRESpeechLib::~CRESpeechLib(){
this->isInit = false;
print("Calling destructor of " + this->id);
this->ttsInterface.unload();
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
void CRESpeechLib::init(int val){
this->isInit = true;
this->id = val;
print("Creating Class: " + this->id);
this->ttsInterface.load();
}
bool CRESpeechLib::say(const std::string &sentence){
bool balik = this->ttsInterface.say(sentence);
return balik;
}
void CRESpeechLib::removeNotify(){
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
ISpVoice* CRESpeechLib::getVoicePointer(){
return this->ttsInterface.getVoicePt();
}
JNIEXPORT jboolean JNICALL Java_com_example_MainClass_speak(JNIEnv *env, jobject obj, jlong ptID, jstring str){
const char *nativeString = env->GetStringUTFChars(str, FALSE);
std::string temp(nativeString);
theString = std::wstring(temp.begin(), temp.end());
jboolean ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
ret = pt->say(nativeString);
env->ReleaseStringUTFChars(str, nativeString);
return ret;
}
JNIEXPORT jobjectArray JNICALL Java_com_example_MainClass_getVoices(JNIEnv *env, jobject thisObj, jlong ptID){
jobjectArray ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
std::vector<std::string> list = pt->getVoices();
ret = (jobjectArray) env->NewObjectArray(list.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
int i = 0;
for (std::vector<std::string>::iterator it = list.begin(); it != list.end(); ++it) {
env->SetObjectArrayElement(ret, i, env->NewStringUTF((*it).c_str()));
i++;
}
return(ret);
}
JNIEXPORT void JNICALL Java_com_example_MainClass_removeNotify(JNIEnv *env, jobject obj, jlong ptID){
//jboolean ret;
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
pt->removeNotify();
return;
}
JNIEXPORT jlong JNICALL Java_com_example_MainClass_createTTS(JNIEnv *env, jobject obj, jint id){
//init variables for the JNI callback
CRESpeechLib *pt = new CRESpeechLib(id);
return (jlong) pt;
}
JNIEXPORT void JNICALL Java_com_example_MainClass_deleteTTS(JNIEnv *env, jobject obj, jlong ptID){
print("Delete called");
CRESpeechLib *pt = (CRESpeechLib *) (ptID);
pt->removeNotify();
delete pt;
delete javaVM;
env->DeleteGlobalRef(javaObj);
return;
}
void __stdcall outsideeventFunction(WPARAM wParam, LPARAM lParam){
//event handling of tts
return;
}
void wordBoundaryCallback(int start, int end) {
//call java method wordBoundaryCallback
}
HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds)
{
//create the pump message
return hr;
}
////////////////////////////JAVA CODES///////////////////////////////////
//Assume all native codes are already declared
public MainClass(){
this.id = 1;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public MainClass(int id){
this.id = id;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public void wordBoundaryReach(int start, int end){
System.out.println("From CB: Start: " + start + "\t\tEnd: " + end);
}
public boolean speak(String msg){
return speak(addressRef, msg);
}
public boolean setVoice(String name){
return setVoice(addressRef, name);
}
public void deleteTTS(){
deleteTTS(addressRef);
}
private void attachShutDownHook(){
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
MainClass.this.deleteTTS(addressRef);
System.out.println("Inside Add Shutdown Hook");
}
});
System.out.println("Shut Down Hook Attached.");
}
public static void main(String[] args) {
MainClass t = new MainClass(1);
String[] s = (String[])t.getVoices();
t.setVoice(s[0]);
if(t.speak("Testing the functionalities from the library. I hope this is fine. Let us try another sentence for the sake of a long speech.")){
System.out.println("Tapos na. Success");
}else{
System.out.println("Tapos na. Failed");
}
System.exit(0);
}
答案 0 :(得分:0)
经过几天的调试,我现在知道问题所在了。
实际上,Runtime.getRuntime().addShutdownHook()
被调用。但问题是我的析构函数从未完成清理指针。我不知道问题是什么,但我使用delete
作为指针。当我扫描我的析构函数时,它总是挂在我调用delete
函数的地方。所以我所做的就是使用c ++ std::unique_ptr
,以便我的指针pt
只调用release
。截至目前,我不知道导致delete
函数挂起的原因。
JavaVM * javaVM;
jobject javaObj;
//different java callback variables
long speechObjId;
std::wstring theString(L"");
std::unique_ptr<CRESpeechLib> pt; //pt now is a global
bool debug;
CRESpeechLib::CRESpeechLib(){
init(1);
}
CRESpeechLib::CRESpeechLib(int val){
init(val);
}
CRESpeechLib::~CRESpeechLib(){
this->isInit = false;
print("Calling destructor of " + this->id);
this->ttsInterface.unload();
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
void CRESpeechLib::init(int val){
this->isInit = true;
this->id = val;
print("Creating Class: " + this->id);
this->ttsInterface.load();
}
bool CRESpeechLib::say(const std::string &sentence){
bool balik = this->ttsInterface.say(sentence);
return balik;
}
void CRESpeechLib::removeNotify(){
this->ttsInterface.getVoicePt()->SetNotifySink(NULL);
}
ISpVoice* CRESpeechLib::getVoicePointer(){
return this->ttsInterface.getVoicePt();
}
JNIEXPORT jboolean JNICALL Java_com_example_MainClass_speak(JNIEnv *env, jobject obj, jstring str){
const char *nativeString = env->GetStringUTFChars(str, FALSE);
std::string temp(nativeString);
theString = std::wstring(temp.begin(), temp.end());
jboolean ret;
//CRESpeechLib *pt = (CRESpeechLib *) (ptID);
ret = pt->say(nativeString);
env->ReleaseStringUTFChars(str, nativeString);
return ret;
}
JNIEXPORT jobjectArray JNICALL Java_com_example_MainClass_getVoices(JNIEnv *env, jobject thisObj){
jobjectArray ret;
//CRESpeechLib *pt = (CRESpeechLib *) (ptID);
std::vector<std::string> list = pt->getVoices();
ret = (jobjectArray) env->NewObjectArray(list.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
int i = 0;
for (std::vector<std::string>::iterator it = list.begin(); it != list.end(); ++it) {
env->SetObjectArrayElement(ret, i, env->NewStringUTF((*it).c_str()));
i++;
}
return(ret);
}
JNIEXPORT void JNICALL Java_com_example_MainClass_removeNotify(JNIEnv *env, jobject obj){
//jboolean ret;
//CRESpeechLib *pt = (CRESpeechLib *) (ptID);
pt->removeNotify();
return;
}
JNIEXPORT void JNICALL Java_com_example_MainClass_createTTS(JNIEnv *env, jobject obj, jint id){
//init variables for the JNI callback
//CRESpeechLib *pt = new CRESpeechLib(id);
pt = std::unique_ptr<CRESpeechLib>(new CRESpeechLib(id));
return;
}
JNIEXPORT void JNICALL Java_com_example_MainClass_deleteTTS(JNIEnv *env, jobject obj){
print("Delete called");
pt.release();
return;
}
void __stdcall outsideeventFunction(WPARAM wParam, LPARAM lParam){
//event handling of tts
return;
}
void wordBoundaryCallback(int start, int end) {
//call java method wordBoundaryCallback
}
HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds)
{
//create the pump message
return hr;
}
////////////////////////////JAVA CODES///////////////////////////////////
//Assume all native codes are already declared
public MainClass(){
this.id = 1;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public MainClass(int id){
this.id = id;
addressRef = createTTS(id);
System.out.println("Class reference: " + addressRef);
this.attachShutDownHook();
}
public void wordBoundaryReach(int start, int end){
System.out.println("From CB: Start: " + start + "\t\tEnd: " + end);
}
private void attachShutDownHook(){
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
MainClass.this.deleteTTS();
System.out.println("Inside Add Shutdown Hook");
}
});
System.out.println("Shut Down Hook Attached.");
}
public static void main(String[] args) {
MainClass t = new MainClass(1);
String[] s = (String[])t.getVoices();
t.setVoice(s[0]);
if(t.speak("Testing the functionalities from the library. I hope this is fine. Let us try another sentence for the sake of a long speech.")){
System.out.println("Tapos na. Success");
}else{
System.out.println("Tapos na. Failed");
}
System.exit(0);
}