/* * Returns an exception (with stack trace) as a string. */ static bool getStackTrace(C_JNIEnv* env, jthrowable exception, std::string& result) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); scoped_local_ref<jclass> stringWriterClass(env, findClass(env, "java/io/StringWriter")); if (stringWriterClass.get() == NULL) { return false; } jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "<init>", "()V"); jmethodID stringWriterToStringMethod = (*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;"); scoped_local_ref<jclass> printWriterClass(env, findClass(env, "java/io/PrintWriter")); if (printWriterClass.get() == NULL) { return false; } jmethodID printWriterCtor = (*env)->GetMethodID(e, printWriterClass.get(), "<init>", "(Ljava/io/Writer;)V"); scoped_local_ref<jobject> stringWriter(env, (*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor)); if (stringWriter.get() == NULL) { return false; } jobject printWriter = (*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get()); if (printWriter == NULL) { return false; } scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail jmethodID printStackTraceMethod = (*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V"); (*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter); if ((*env)->ExceptionCheck(e)) { return false; } scoped_local_ref<jstring> messageStr(env, (jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod)); if (messageStr.get() == NULL) { return false; } const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (utfChars == NULL) { return false; } result = utfChars; (*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars); return true; }
/* * Returns a human-readable summary of an exception object. The buffer will * be populated with the "binary" class name and, if present, the * exception message. */ static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); /* get the name of the exception's class */ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail scoped_local_ref<jclass> classClass(env, (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail jmethodID classGetNameMethod = (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;"); scoped_local_ref<jstring> classNameStr(env, (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod)); if (classNameStr.get() == NULL) { (*env)->ExceptionClear(e); result = "<error getting class name>"; return false; } const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL); if (classNameChars == NULL) { (*env)->ExceptionClear(e); result = "<error getting class name UTF-8>"; return false; } result += classNameChars; (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars); /* if the exception has a detail message, get that */ jmethodID getMessage = (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;"); scoped_local_ref<jstring> messageStr(env, (jstring) (*env)->CallObjectMethod(e, exception, getMessage)); if (messageStr.get() == NULL) { return true; } result += ": "; const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (messageChars != NULL) { result += messageChars; (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars); } else { result += "<error getting message>"; (*env)->ExceptionClear(e); // clear OOM } return true; }
/* * Returns a human-readable summary of an exception object. The buffer will * be populated with the "binary" class name and, if present, the * exception message. */ static char* getExceptionSummary0(C_JNIEnv* env, jthrowable exception) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); /* get the name of the exception's class */ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail scoped_local_ref<jclass> classClass(env, (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail jmethodID classGetNameMethod = (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;"); scoped_local_ref<jstring> classNameStr(env, (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod)); if (classNameStr.get() == NULL) { return NULL; } /* get printable string */ const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL); if (classNameChars == NULL) { return NULL; } /* if the exception has a detail message, get that */ jmethodID getMessage = (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;"); scoped_local_ref<jstring> messageStr(env, (jstring) (*env)->CallObjectMethod(e, exception, getMessage)); if (messageStr.get() == NULL) { return strdup(classNameChars); } char* result = NULL; const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (messageChars != NULL) { asprintf(&result, "%s: %s", classNameChars, messageChars); (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars); } else { (*env)->ExceptionClear(e); // clear OOM asprintf(&result, "%s: <error getting message>", classNameChars); } (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars); return result; }
void _APIENTRY OpenGLDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam) { std::string sourceStr; std::string typeStr; std::string severityStr; std::string messageStr(message, length); switch (source) { case GL_DEBUG_SOURCE_API_ARB: sourceStr = "API"; break; case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: sourceStr = "WindowSystem"; break; case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: sourceStr = "Shader"; break; case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: sourceStr = "3rd Party"; break; case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceStr = "Application"; break; case GL_DEBUG_SOURCE_OTHER_ARB: sourceStr = "other"; break; default: sourceStr = "unknown"; } switch (type) { case GL_DEBUG_TYPE_ERROR_ARB: typeStr = "error"; break; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typeStr = "deprecated"; break; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typeStr = "undefined"; break; case GL_DEBUG_TYPE_PORTABILITY_ARB: typeStr = "portability"; break; case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeStr = "peformance"; break; case GL_DEBUG_TYPE_OTHER_ARB: typeStr = "other"; break; default: typeStr = "unknown"; } switch (severity) { case GL_DEBUG_SEVERITY_HIGH_ARB: severityStr = "high"; break; case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityStr = "medium"; break; case GL_DEBUG_SEVERITY_LOW_ARB: severityStr = "low"; break; default: severityStr = "unknown"; } LOG_L(L_ERROR, "OpenGL: source<%s> type<%s> id<%u> severity<%s>:\n%s", sourceStr.c_str(), typeStr.c_str(), id, severityStr.c_str(), messageStr.c_str()); }