Пример #1
0
/*
 * Throw an exception with the specified class and an optional message.
 *
 * If an exception is currently pending, we log a warning message and
 * clear it.
 *
 * Returns 0 if the specified exception was successfully thrown.  (Some
 * sort of exception will always be pending when this returns.)
 */
int jniThrowException(JNIEnv* env, const char* className, const char* msg)
{
    jclass exceptionClass;

    if ((*env)->ExceptionCheck(env)) {
        /* TODO: consider creating the new exception with this as "cause" */
        char buf[256];

        jthrowable exception = (*env)->ExceptionOccurred(env);
        (*env)->ExceptionClear(env);

        if (exception != NULL) {
            getExceptionSummary(env, exception, buf, sizeof(buf));
            LOGW("Discarding pending exception (%s) to throw %s\n", buf, className);
            (*env)->DeleteLocalRef(env, exception);
        }
    }

    exceptionClass = (*env)->FindClass(env, className);
    if (exceptionClass == NULL) {
        LOGE("Unable to find exception class %s\n", className);
        /* ClassNotFoundException now pending */
        return -1;
    }

    int result = 0;
    if ((*env)->ThrowNew(env, exceptionClass, msg) != JNI_OK) {
        LOGE("Failed throwing '%s' '%s'\n", className, msg);
        /* an exception, most likely OOM, will now be pending */
        result = -1;
    }

    (*env)->DeleteLocalRef(env, exceptionClass);
    return result;
}
Пример #2
0
extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    if ((*env)->ExceptionCheck(e)) {
        /* TODO: consider creating the new exception with this as "cause" */
        scoped_local_ref<jthrowable> exception(env, (*env)->ExceptionOccurred(e));
        (*env)->ExceptionClear(e);

        if (exception.get() != NULL) {
            std::string text;
            getExceptionSummary(env, exception.get(), text);
            ALOGW("Discarding pending exception (%s) to throw %s", text.c_str(), className);
        }
    }

    scoped_local_ref<jclass> exceptionClass(env, findClass(env, className));
    if (exceptionClass.get() == NULL) {
        ALOGE("Unable to find exception class %s", className);
        /* ClassNotFoundException now pending */
        return -1;
    }

    if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) {
        ALOGE("Failed throwing '%s' '%s'", className, msg);
        /* an exception, most likely OOM, will now be pending */
        return -1;
    }

    return 0;
}
Пример #3
0
extern "C" std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e));
    if (exception == NULL) {
        exception = currentException.get();
        if (exception == NULL) {
          return "<no pending exception>";
        }
    }

    if (currentException.get() != NULL) {
        (*env)->ExceptionClear(e);
    }

    std::string trace;
    if (!getStackTrace(env, exception, trace)) {
        (*env)->ExceptionClear(e);
        getExceptionSummary(env, exception, trace);
    }

    if (currentException.get() != NULL) {
        (*env)->Throw(e, currentException.get()); // rethrow
    }

    return trace;
}
Пример #4
0
void jniLogException(C_JNIEnv* env, int priority, const char* tag,
		jthrowable exception) {
	JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

	scoped_local_ref<jthrowable> currentException(env,
			(*env)->ExceptionOccurred(e));
	if (exception == NULL) {
		exception = currentException.get();
		if (exception == NULL) {
			return;
		}
	}

	if (currentException.get() != NULL) {
		(*env)->ExceptionClear(e);
	}

	char* buffer = getStackTrace(env, exception);
	if (buffer == NULL) {
		(*env)->ExceptionClear(e);
		buffer = getExceptionSummary(env, exception);
	}

	__android_log_write(priority, tag, buffer);
	free(buffer);

	if (currentException.get() != NULL) {
		(*env)->Throw(e, currentException.get()); // rethrow
	}
}
Пример #5
0
/*
 * Formats an exception as a string with its stack trace.
 */
static void printStackTrace(JNIEnv* env, jthrowable exception, char* buf, size_t bufLen)
{
    int success = 0;

    jclass stringWriterClazz = (*env)->FindClass(env, "java/io/StringWriter");
    if (stringWriterClazz != NULL) {
        jmethodID stringWriterCtor = (*env)->GetMethodID(env, stringWriterClazz,
                "<init>", "()V");
        jmethodID stringWriterToStringMethod = (*env)->GetMethodID(env, stringWriterClazz,
                "toString", "()Ljava/lang/String;");

        jclass printWriterClazz = (*env)->FindClass(env, "java/io/PrintWriter");
        if (printWriterClazz != NULL) {
            jmethodID printWriterCtor = (*env)->GetMethodID(env, printWriterClazz,
                    "<init>", "(Ljava/io/Writer;)V");

            jobject stringWriterObj = (*env)->NewObject(env, stringWriterClazz, stringWriterCtor);
            if (stringWriterObj != NULL) {
                jobject printWriterObj = (*env)->NewObject(env, printWriterClazz, printWriterCtor,
                        stringWriterObj);
                if (printWriterObj != NULL) {
                    jclass exceptionClazz = (*env)->GetObjectClass(env, exception); // can't fail
                    jmethodID printStackTraceMethod = (*env)->GetMethodID(
                            env, exceptionClazz, "printStackTrace", "(Ljava/io/PrintWriter;)V");

                    (*env)->CallVoidMethod(
                            env, exception, printStackTraceMethod, printWriterObj);
                    if (! (*env)->ExceptionCheck(env)) {
                        jstring messageStr = (*env)->CallObjectMethod(
                                env, stringWriterObj, stringWriterToStringMethod);
                        if (messageStr != NULL) {
                            jsize messageStrLength = (*env)->GetStringLength(env, messageStr);
                            if (messageStrLength >= (jsize) bufLen) {
                                messageStrLength = bufLen - 1;
                            }
                            (*env)->GetStringUTFRegion(env, messageStr, 0, messageStrLength, buf);
                            (*env)->DeleteLocalRef(env, messageStr);
                            buf[messageStrLength] = '\0';
                            success = 1;
                        }
                    }
                    (*env)->DeleteLocalRef(env, exceptionClazz);
                    (*env)->DeleteLocalRef(env, printWriterObj);
                }
                (*env)->DeleteLocalRef(env, stringWriterObj);
            }
            (*env)->DeleteLocalRef(env, printWriterClazz);
        }
        (*env)->DeleteLocalRef(env, stringWriterClazz);
    }

    if (! success) {
        (*env)->ExceptionClear(env);
        getExceptionSummary(env, exception, buf, bufLen);
    }
}