문제

내 일관적이고 간단한 방법으로 던지는 예외에는 사용자 코드가 처리하는 연결된 예외(암시적으로에서 env->ExceptionOccurred 방법,또는 명시적으로 매개변수에 의하여,어느 쪽이든 좋은 것)과 나를 저장을 찾 생성자를 모든 시간이 이런 걸 하고 싶어요.위의 모든 것이 바람직하에서는 C,도 있겠지만 그것을 번역에서는 C++에서는 필요합니다.

사람에게 같은 것을 가지고 있는 이들이 공유할 수 있습?

도움이 되었습니까?

해결책

우리는 코드 유틸리티를 위한 방법의 유형의 각각을 우리가 원하는 예외를 던져.여기에 몇 가지 예가 나와 있습니다.

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.

내 코드는 Java에서 시작하여 C ++를 호출 한 다음 필드 값을 찾고, 얻고, 설정하는 것과 같은 것들을 위해 Java를 다시 호출합니다.

C ++ 접근 방식을 찾는 사람 이이 페이지를 찾으면 다음과 같이 쟁기질을 할 것입니다.

내가 지금하고있는 일은 C ++ 시도/캐치 블록으로 내 JNI 메소드 본문을 포장하는 것입니다.

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 */
    }
}

보급 예고가 사소하게 선언 된 경우 :

class PendingException {};

그리고 C ++에서 JNI를 호출 한 후 다음 방법을 호출하고 있으므로 Java 예외 상태 상태에 오류가 표시되면 즉시 보석금을 내고 일반 Java 예외 처리가 스택 추적에 (기본 메소드) 라인을 추가하도록합니다. C ++에게 풀어주는 동안 정리할 수있는 기회를 제공합니다.

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

내 Java Stack Trace는 실패한 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 방법을 부르면 꽤 비슷합니다.

 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 ++ 내에서 다른 Java 예외 내에서 Java Exception을 다른 Java 예외 내에서 포장하는 것에 대해 이야기 할 수 없습니다. 나는 그렇게 할 필요가 없었습니다. 그러나 내가 그렇게했다면, 나는 그것을 할 것입니다. 기본 방법 주변의 Java 수준의 래퍼 또는 예외적 인 방법을 확장하여 jthrowable을 취하고 Env-> 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);
}

예외는 일반적인 제어 흐름 메커니즘으로 여겨지지 않기 때문에 캐싱 (예외) 클래스 생성자 참조를 고려하지 않으므로 속도가 느려도 중요하지 않습니다. Java는 아마도 그런 종류의 일을 위해 자체 캐싱을하고 있기 때문에 어쨌든 룩업이 굉장히 느리지 않다고 생각합니다.

나는 이전에 필요한 것처럼 조금 더 많은 설명이 필요한 사람에게 더 완전하고 일반적인 답변을 드리겠습니다.

먼저 방법을 설정하는 것이 좋습니다 Throw Exception 따라서 IDE는 시도/캐치를 요구할 것입니다.

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