سؤال

وأود بطريقة متسقة وبسيطة لرمي الاستثناءات في قانون JNI. وهو الأمر الذي يتعامل مع استثناءات بالسلاسل (ضمنيا من env-> طريقة ExceptionOccurred، أو صراحة المعلمات، اما الطريقة جيدة) ويحفظ لي يبحث حتى الصانعين في كل مرة أريد أن أفعل هذا. كل ما سبق هو يفضل في C، على الرغم من أنني يمكن ترجمته من C ++ في حاجة إليها.

هل أي شخص على أن يكون SO شيئا من هذا القبيل التي يمكن أن حصة؟

هل كانت مفيدة؟

المحلول

ونحن فقط كود طرق فائدة لكل من أنواع الاستثناءات نريد لرمي. وفيما يلي بعض الأمثلة على ذلك:

jint throwNoClassDefError( JNIEnv *env, char *message )
{
    jclass exClass;
    char *className = "java/lang/NoClassDefFoundError";

    exClass = (*env)->FindClass( env, className);
    if (exClass == NULL) {
        return throwNoClassDefError( env, className );
    }

    return (*env)->ThrowNew( env, exClass, message );
}

jint throwNoSuchMethodError(
        JNIEnv *env, char *className, char *methodName, char *signature )
{

    jclass exClass;
    char *exClassName = "java/lang/NoSuchMethodError" ;
    LPTSTR msgBuf;
    jint retCode;
    size_t nMallocSize;

    exClass = (*env)->FindClass( env, exClassName );
    if ( exClass == NULL ) {
        return throwNoClassDefError( env, exClassName );
    }

    nMallocSize = strlen(className) 
            + strlen(methodName)
            + strlen(signature) + 8;

    msgBuf = malloc( nMallocSize );
    if ( msgBuf == NULL ) {
        return throwOutOfMemoryError
                ( env, "throwNoSuchMethodError: allocating msgBuf" );
    }
    memset( msgBuf, 0, nMallocSize );

    strcpy( msgBuf, className );
    strcat( msgBuf, "." );
    strcat( msgBuf, methodName );
    strcat( msgBuf, "." );
    strcat( msgBuf, signature );

    retCode = (*env)->ThrowNew( env, exClass, msgBuf );
    free ( msgBuf );
    return retCode;
}

jint throwNoSuchFieldError( JNIEnv *env, char *message )
{
    jclass exClass;
    char *className = "java/lang/NoSuchFieldError" ;

    exClass = (*env)->FindClass( env, className );
    if ( exClass == NULL ) {
        return throwNoClassDefError( env, className );
    }

    return (*env)->ThrowNew( env, exClass, message );
}

jint throwOutOfMemoryError( JNIEnv *env, char *message )
{
    jclass exClass;
    char *className = "java/lang/OutOfMemoryError" ;

    exClass = (*env)->FindClass( env, className );
    if ( exClass == NULL ) {
        return throwNoClassDefError( env, className );
    }

    return (*env)->ThrowNew( env, exClass, message );
}

وبهذه الطريقة، فإنه من السهل للعثور عليهم، سيكون لديك محرر مدونة الإنجاز تساعدك على كتابتها في، ويمكنك تمرير المعلمات بسيطة.

وأنا متأكد من أنك يمكن أن يتوسع هذا لمعالجة الاستثناءات بالسلاسل، أو غيرها من الأساليب أكثر تعقيدا. كان هذا كافيا لتلبية احتياجاتنا.

نصائح أخرى

وأنا ببساطة استخدام خطوط 2:

 sprintf(exBuffer, "NE%4.4X: Caller can %s %s print", marker, "log", "or");
 (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), exBuffer);

وتنتج:

 Exception in thread "main" java.lang.Exception: NE0042: Caller can log or print.

ويبدأ كود بلدي في جاوة، استدعاء C ++، والتي ثم استدعاء جافا مرة أخرى لأشياء مثل العثور على، والحصول، ووضع قيم الحقول.

في حالة شخص يبحثون عن C ++ النهج يجد هذه الصفحة، سوف محراث مع هذا:

ما أفعله الآن هو التفاف بلدي الهيئات طريقة JNI حتى مع C ++ محاولة / كتلة التقاط

JNIEXPORT void JNICALL Java_com_pany_jni_JNIClass_something(JNIEnv* env, jobject self)
{
    try
    {
        ... do JNI stuff
        // return something; if not void.
    }
    catch (PendingException e) // (Should be &e perhaps?)
    {
        /* any necessary clean-up */
    }
}

وحيث أعلن PendingException مسلي:

class PendingException {};

وأنا استدعاء الأسلوب التالي بعد استدعاء أي JNI من C ++، حتى إذا كان يشير إلى حالة استثناء جافا خطأ، وأنا إنقاذ فورا والسماح للجافا معالجة الاستثناء العادي إضافة (طريقة الأصلي) خط إلى المكدس أثر، في حين يعطي C ++ الفرصة لتنظيف بينما الفك:

PendingException PENDING_JNI_EXCEPTION;
void throwIfPendingException(JNIEnv* env)
{
    if (env->ExceptionCheck()) {
        throw PENDING_JNI_EXCEPTION;
    }
}

وبلدي جافا تتبع مكدس يشبه هذا لمكالمة فشل env-> GetFieldId ():

java.lang.NoSuchFieldError: no field with name='opaque' signature='J' in class Lcom/pany/jni/JniClass;
  at com.pany.jni.JniClass.construct(Native Method)
  at com.pany.jni.JniClass.doThing(JniClass.java:169)
  at com.pany.jni.JniClass.access$1(JniClass.java:151)
  at com.pany.jni.JniClass$2.onClick(JniClass.java:129)
  at android.view.View.performClick(View.java:4084)

ووتشبه إلى حد ما إذا كنت استدعاء ما يصل الى طريقة جافا يطرح:

 java.lang.RuntimeException: YouSuck
  at com.pany.jni.JniClass.fail(JniClass.java:35)
  at com.pany.jni.JniClass.getVersion(Native Method)
  at com.pany.jni.JniClass.doThing(JniClass.java:172)

وأنا لا أستطيع التحدث مع التفاف استثناء جافا داخل استثناء جافا آخر من داخل C ++، وهو ما أعتقد هو جزء من سؤالك - لقد لم يتم العثور على الحاجة لفعل ذلك - ولكن إذا فعلت ذلك، يهمني سواء تفعل ذلك مع المجمع على مستوى جافا حول أساليب الأم، أو مجرد أتقدم أساليب رمي استثناء لاتخاذ jthrowable واستبدال env-> ThrowNew () الاتصال مع شيء قبيح: من المؤسف الشمس لم تقدم نسخة من ThrowNew التي أخذت jthrowable.

void impendNewJniException(JNIEnv* env, const char *classNameNotSignature, const char *message)
{
    jclass jClass = env->FindClass(classNameNotSignature);
    throwIfPendingException(env);
    env->ThrowNew(jClass, message);
}

void throwNewJniException(JNIEnv* env, const char* classNameNotSignature, const char* message)
{
    impendNewJniException(env, classNameNotSignature, message);
    throwIfPendingException(env);
}

وأود أن لا تنظر المراجع التخزين المؤقت (استثناء) فئة منشئ لأن الاستثناءات لا يفترض أن تكون آلية التحكم في التدفق المعتاد، لذلك لا ينبغي أن المسألة لو انهم بطيئة. أتصور تبدو المتابعة ليست بطيئة بشكل رهيب على أي حال، منذ جافا يفترض يفعل التخزين المؤقت الخاصة به لهذا النوع من الشيء.

وسوف أضع إجابة أكثر اكتمالا والعامة لمنظمة الصحة العالمية تحتاج قليلا المزيد من التفسيرات مثل أحتاج من قبل.

والأول هو لطيفة لتحديد طريقتك مع Throw Exception ذلك IDE سيطلب حاول / catch.

public native int func(Param1, Param2, Param3) throws IOException;

وأقرر لIOException على Exception بسبب هذا .

JNIEXPORT int JNICALL Java_YourClass_func
(int Param1, int Param2, int Param3) {
    if (Param3 == 0) { //something wrong
        jclass Exception = env->FindClass("java/lang/Exception");
        env->ThrowNew(Exception, "Can't divide by zero."); // Error Message
    }
    return (Param1+Param2)/Param3;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top