2012-05-02 13 views
13

मैं यह निर्धारित करना चाहता हूं कि जेएनआई का उपयोग कर सी ++ कोड से उस फ़ंक्शन को कॉल करते समय जावा फ़ंक्शन द्वारा कौन सा अपवाद फेंक दिया गया है।जेएनआई का उपयोग करते समय सी ++ में जावा अपवाद का वर्णन कैसे प्राप्त करें?

JNIEnv * pEnv; // assume this is properly initialized 
jclass javaClass; // ditto 
jmethodID javaFunction; // ditto 
pEnv->CallStaticVoidMethod(javaClass, javaFunction); 
jthrowable exc; 
if(exc = pEnv->ExceptionOccurred()) 
{ 
    pEnv->ExceptionClear(); 
} 

मैं इस सी ++ कोड के भीतर जावा अपवाद बारे में वर्णनात्मक जानकारी प्राप्त करने के लिए पता नहीं कैसे: मैं निम्नलिखित कोड है कि जावा अपवाद पकड़ता है। क्या कोई मदद कर सकता है?

+1

तो आप सभी की जरूरत उत्पादन के लिए डीबगिंग उद्देश्यों के लिए stderr को यह जानकारी है, तो आप ExceptionDescribe() सुविधा विधि का उपयोग कर सकते हैं। –

+0

ऐसा लगता है कि सी ++ में कुछ भी नहीं है। मेरे मामले में, सी ++ निष्पादन योग्य है, और जावा चल रहे C++ अनुप्रयोग के संदर्भ में लोड किया गया है। –

+0

यह वही काम करता है जैसे 'exc.printStackTrace() '। – EJP

उत्तर

16

मैंने प्रत्येक जेएनआई कॉल के बाद ExceptionCheck() पर कॉल छोड़ दिया है और ब्रेवटी के तरीकों का पता लगाने के किसी भी असफल प्रयास की जांच की है: आपको इसे लागू करते समय इन्हें जोड़ना चाहिए।

पहले, अपवाद की दुकान और फिर Throwable के बारे में जानकारी प्राप्त करने के लिए आवश्यक जावा तरीकों के अधिग्रहण:

// Get the exception and clear as no 
// JNI calls can be made while an exception exists. 
jthrowable exception = pEnv->ExceptionOccurred(); 
pEnv->ExceptionClear(); 

jclass throwable_class = pEnv->FindClass("java/lang/Throwable"); 
jmethodID mid_throwable_getCause = 
    pEnv->GetMethodID(throwable_class, 
         "getCause", 
         "()Ljava/lang/Throwable;"); 
jmethodID mid_throwable_getStackTrace = 
    pEnv->GetMethodID(throwable_class, 
         "getStackTrace", 
         "()[Ljava/lang/StackTraceElement;"); 
jmethodID mid_throwable_toString = 
    pEnv->GetMethodID(throwable_class, 
         "toString", 
         "()Ljava/lang/String;"); 

jclass frame_class = pEnv->FindClass("java/lang/StackTraceElement"); 
jmethodID mid_frame_toString = 
    pEnv->GetMethodID(frame_class, 
         "toString", 
         "()Ljava/lang/String;"); 

दूसरा, रिकर्सिवली त्रुटि संदेश का निर्माण (आप इस संशोधित करने के लिए चाहते हो सकता है):

std::string error_msg; // Could use ostringstream instead. 

_append_exception_trace_messages(*pEnv, 
           error_msg, 
           exception, 
           mid_throwable_getCause, 
           mid_throwable_getStackTrace, 
           mid_throwable_toString, 
           mid_frame_toString); 

void _append_exception_trace_messages(
         JNIEnv&  a_jni_env, 
         std::string& a_error_msg, 
         jthrowable a_exception, 
         jmethodID a_mid_throwable_getCause, 
         jmethodID a_mid_throwable_getStackTrace, 
         jmethodID a_mid_throwable_toString, 
         jmethodID a_mid_frame_toString) 
{ 
    // Get the array of StackTraceElements. 
    jobjectArray frames = 
     (jobjectArray) a_jni_env.CallObjectMethod(
             a_exception, 
             a_mid_throwable_getStackTrace); 
    jsize frames_length = a_jni_env.GetArrayLength(frames); 

    // Add Throwable.toString() before descending 
    // stack trace messages. 
    if (0 != frames) 
    { 
     jstring msg_obj = 
      (jstring) a_jni_env.CallObjectMethod(a_exception, 
               a_mid_throwable_toString); 
     const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0); 

     // If this is not the top-of-the-trace then 
     // this is a cause. 
     if (!a_error_msg.empty()) 
     { 
      a_error_msg += "\nCaused by: "; 
      a_error_msg += msg_str; 
     } 
     else 
     { 
      a_error_msg = msg_str; 
     } 

     a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str); 
     a_jni_env.DeleteLocalRef(msg_obj); 
    } 

    // Append stack trace messages if there are any. 
    if (frames_length > 0) 
    { 
     jsize i = 0; 
     for (i = 0; i < frames_length; i++) 
     { 
      // Get the string returned from the 'toString()' 
      // method of the next frame and append it to 
      // the error message. 
      jobject frame = a_jni_env.GetObjectArrayElement(frames, i); 
      jstring msg_obj = 
       (jstring) a_jni_env.CallObjectMethod(frame, 
                a_mid_frame_toString); 

      const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0); 

      a_error_msg += "\n "; 
      a_error_msg += msg_str; 

      a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str); 
      a_jni_env.DeleteLocalRef(msg_obj); 
      a_jni_env.DeleteLocalRef(frame); 
     } 
    } 

    // If 'a_exception' has a cause then append the 
    // stack trace messages from the cause. 
    if (0 != frames) 
    { 
     jthrowable cause = 
      (jthrowable) a_jni_env.CallObjectMethod(
          a_exception, 
          a_mid_throwable_getCause); 
     if (0 != cause) 
     { 
      _append_exception_trace_messages(a_jni_env, 
              a_error_msg, 
              cause, 
              a_mid_throwable_getCause, 
              a_mid_throwable_getStackTrace, 
              a_mid_throwable_toString, 
              a_mid_frame_toString); 
     } 
    } 
} 

मैंने इसे कोड से कॉपी किया है जिसे मैंने कुछ साल पहले लिखा था (बॉयलर प्लेट ExceptionCheck() एस को खत्म करने के लिए संशोधित), लेकिन मैंने जो कुछ पोस्ट किया है उसे संकलित नहीं किया है लेकिन सामान्य दृष्टिकोण उम्मीद है कि स्पष्ट रूप से स्पष्ट है।

jthrowable throwable = ExceptionOccurred(env); 
if (throwable != NULL) 
    Throw(env, throwable); 

और इसके साथ अपने जावा कोड सौदा करते हैं:

+0

उत्कृष्ट, धन्यवाद। मैं इसे अगले दिन या दो में बनाऊंगा और फिर इसे उत्तर के रूप में चिह्नित करूंगा। बहुत बुरा जेएनआई स्वचालित रूप से सभी की देखभाल करने के लिए एक समारोह प्रदान नहीं करता है - एक कमजोरी। –

+1

@DanNissenbaum, एक बेहतर तरीका हो सकता है लेकिन यह एकमात्र तरीका है जिसे मैं पा सकता हूं। यह कम से कम कहने के लिए निरंतर 'अपवाद चेक() ') के साथ काफी verbose (और भी अधिक है। – hmjd

+0

आपका कोड एक ही बदलाव के बिना काम करता है। धन्यवाद। (मैं सुरक्षा जांच जोड़ रहा हूं, आदि) –

-1

इस से बाहर आसान तरीका सभी संभव अपवाद हैं, तो फेंक JNI प्रणाली की घोषणा की जाती है।

+0

क्या यह संभव है कि जावा कोड पूरी तरह से बाहर निकल गया हो - यानी, यह एक सी ++ निष्पादन योग्य है जो एक एकल जावा फ़ंक्शन को कॉल करता है, जो अपवाद के साथ निकलता है? –

+0

@DanNissenbaum बिल्कुल नहीं। यदि कोई जावा कोड नहीं है तो यह अपवाद से निपट नहीं सकता है। – EJP

+0

इसलिए, मेरे प्रश्न का कारण। –

0

तुम सिर्फ अपवाद आप कर सकते हैं की स्टैक ट्रेस में रुचि रखते हैं:

if (env->ExceptionOccurred()) // check if an exception occurred 
{ 
    env->ExceptionDescribe(); // print the stack trace   
} 
संबंधित मुद्दे