From a174f452fc48735da7ee49ab5c906528f87b77b5 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Thu, 9 Jan 2014 22:56:28 +0100 Subject: [PATCH 26/39] Surround all JNI calls in try catch all block Related to rhbz#1051198 --- src/abrt-checker.c | 273 ++++++++++++++++++------------------------ src/jthrowable_circular_buf.c | 40 ++++++- 2 files changed, 155 insertions(+), 158 deletions(-) diff --git a/src/abrt-checker.c b/src/abrt-checker.c index fb0c0eb..b6f11e8 100644 --- a/src/abrt-checker.c +++ b/src/abrt-checker.c @@ -631,6 +631,26 @@ static void report_stacktrace( /* + * Returns logical true if exception occurred and clears it. + */ +static inline int check_and_clear_exception( + JNIEnv *jni_env) +{ + if ((*jni_env)->ExceptionOccurred(jni_env)) + { +#ifdef VERBOSE + (*jni_env)->ExceptionDescribe(jni_env); +#endif + (*jni_env)->ExceptionClear(jni_env); + return 1; + } + + return 0; +} + + + +/* * Print a message when any JVM TI error occurs. */ static void print_jvmti_error( @@ -666,12 +686,13 @@ static int get_tid( } jmethodID get_id = (*jni_env)->GetMethodID(jni_env, thread_class, "getId", "()J" ); - if (NULL == get_id) + if (check_and_clear_exception(jni_env) || NULL == get_id) { - VERBOSE_PRINT("Cannot method java.lang.Thread.getId()J\n"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/Thread.getId()J\n"); return 1; } + /* Thread.getId() throws nothing */ *tid = (*jni_env)->CallLongMethod(jni_env, thr, get_id); return 0; @@ -908,7 +929,6 @@ static void get_thread_name( } - /* * Read executable name from link /proc/${PID}/exe */ @@ -1068,7 +1088,7 @@ static char *get_main_class( char *class_name; error_code = (*jvmti_env)->GetSystemProperty(jvmti_env, "sun.java.command", &class_name); - if (error_code != JVMTI_ERROR_NONE) + if (error_code != JVMTI_ERROR_NONE || NULL == class_name) { return UNKNOWN_CLASS_NAME; } @@ -1081,26 +1101,10 @@ static char *get_main_class( string_replace(class_name, '.', '/'); jclass cls = (*jni_env)->FindClass(jni_env, class_name); - /* Throws: - * ClassFormatError: if the class data does not specify a valid class. - * ClassCircularityError: if a class or interface would be its own superclass or superinterface. - * NoClassDefFoundError: if no definition for a requested class or interface can be found. - * OutOfMemoryError: if the system runs out of memory. - */ - - jthrowable exception; - exception = (*jni_env)->ExceptionOccurred(jni_env); - if (exception) + if (check_and_clear_exception(jni_env) || cls == NULL) { - (*jni_env)->ExceptionClear(jni_env); - } - - if (cls == NULL) - { - if (class_name != NULL) - { - (*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)class_name); - } + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of %s\n", class_name); + (*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)class_name); return UNKNOWN_CLASS_NAME; } @@ -1428,6 +1432,7 @@ static char* get_path_to_class_class_loader( char *class_name, const char *stringize_method_name) { + char *out = NULL; jclass class_loader_class = NULL; char *upd_class_name = (char*)malloc(strlen(class_name) + sizeof("class") + 1); @@ -1442,47 +1447,18 @@ static char* get_path_to_class_class_loader( /* find ClassLoader class */ class_loader_class = (*jni_env)->FindClass(jni_env, "java/lang/ClassLoader"); - /* Throws: - * ClassFormatError: if the class data does not specify a valid class. - * ClassCircularityError: if a class or interface would be its own superclass or superinterface. - * NoClassDefFoundError: if no definition for a requested class or interface can be found. - * OutOfMemoryError: if the system runs out of memory. - */ - - /* check if exception was thrown from FindClass() method */ - jthrowable exception; - exception = (*jni_env)->ExceptionOccurred(jni_env); - if (exception) - { - (*jni_env)->ExceptionClear(jni_env); - free(upd_class_name); - return NULL; - } - - if (class_loader_class == NULL) + if (check_and_clear_exception(jni_env) || class_loader_class == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/ClassLoader\n"); free(upd_class_name); return NULL; } /* find method ClassLoader.getResource() */ - jmethodID get_resource = (*jni_env)->GetMethodID(jni_env, class_loader_class, "getResource", "(Ljava/lang/String;)Ljava/net/URL;" ); - /* Throws: - * NoSuchMethodError: if the specified method cannot be found. - * ExceptionInInitializerError: if the class initializer fails due to an exception. - * OutOfMemoryError: if the system runs out of memory. - */ - - exception = (*jni_env)->ExceptionOccurred(jni_env); - if (exception) - { - free(upd_class_name); - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - return NULL; - } - - if (get_resource == NULL) + jmethodID get_resource = (*jni_env)->GetMethodID(jni_env, class_loader_class, "getResource", "(Ljava/lang/String;)Ljava/net/URL;"); + if (check_and_clear_exception(jni_env) || get_resource == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/ClassLoader.getResource(Ljava/lang/String;)Ljava/net/URL;\n"); free(upd_class_name); (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); return NULL; @@ -1491,52 +1467,46 @@ static char* get_path_to_class_class_loader( /* convert new class name into a Java String */ jstring j_class_name = (*jni_env)->NewStringUTF(jni_env, upd_class_name); free(upd_class_name); + if (check_and_clear_exception(jni_env)) + { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not allocate a new UTF string for '%s'\n", upd_class_name); + goto get_path_to_class_class_loader_lcl_refs_cleanup; + } /* call method ClassLoader.getResource(className) */ jobject url = (*jni_env)->CallObjectMethod(jni_env, class_loader, get_resource, j_class_name); - if ((*jni_env)->ExceptionCheck(jni_env)) + if (check_and_clear_exception(jni_env) || NULL == url) { - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - (*jni_env)->DeleteLocalRef(jni_env, j_class_name); - (*jni_env)->ExceptionClear(jni_env); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a resource of %s\n", class_name); + goto get_path_to_class_class_loader_lcl_refs_cleanup; } - if (url == NULL) + + /* find method URL.toString() */ + jclass url_class = (*jni_env)->FindClass(jni_env, "java/net/URL"); + if (check_and_clear_exception(jni_env) || NULL == url_class) { - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - (*jni_env)->DeleteLocalRef(jni_env, j_class_name); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/net/URL\n"); + goto get_path_to_class_class_loader_lcl_refs_cleanup; } - /* find method URL.toString() */ - jmethodID to_external_form = (*jni_env)->GetMethodID(jni_env, (*jni_env)->FindClass(jni_env, "java/net/URL"), stringize_method_name, "()Ljava/lang/String;" ); - /* Throws: - * NoSuchMethodError: if the specified method cannot be found. - * ExceptionInInitializerError: if the class initializer fails due to an exception. - * OutOfMemoryError: if the system runs out of memory. - */ - exception = (*jni_env)->ExceptionOccurred(jni_env); - if (exception) + jmethodID to_external_form = (*jni_env)->GetMethodID(jni_env, url_class, stringize_method_name, "()Ljava/lang/String;"); + if (check_and_clear_exception(jni_env) || NULL == to_external_form) { - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - (*jni_env)->DeleteLocalRef(jni_env, j_class_name); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/net/URL.%s()Ljava/lang/String;\n", stringize_method_name); + goto get_path_to_class_class_loader_lcl_refs_cleanup; } /* call method URL.toString() */ jstring jstr = (jstring)(*jni_env)->CallObjectMethod(jni_env, url, to_external_form); - /* no exception expected */ - - if (jstr == NULL) + if (check_and_clear_exception(jni_env) || jstr == NULL) { - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - (*jni_env)->DeleteLocalRef(jni_env, j_class_name); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to convert an URL object to a string\n"); + goto get_path_to_class_class_loader_lcl_refs_cleanup; } /* convert Java String into C char* */ char *str = (char*)(*jni_env)->GetStringUTFChars(jni_env, jstr, NULL); - char *out = strdup(str); + out = strdup(str); if (out == NULL) { fprintf(stderr, "strdup(): out of memory"); @@ -1544,6 +1514,8 @@ static char* get_path_to_class_class_loader( /* cleanup */ (*jni_env)->ReleaseStringUTFChars(jni_env, jstr, str); + +get_path_to_class_class_loader_lcl_refs_cleanup: (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); (*jni_env)->DeleteLocalRef(jni_env, j_class_name); return out; @@ -1558,39 +1530,30 @@ static jobject get_system_class_loader( jvmtiEnv *jvmti_env __UNUSED_VAR, JNIEnv *jni_env) { + jobject system_class_loader = NULL; + jclass class_loader_class = (*jni_env)->FindClass(jni_env, "java/lang/ClassLoader"); - if (NULL == class_loader_class) + if (check_and_clear_exception(jni_env) || NULL == class_loader_class) { - VERBOSE_PRINT("Cannot find java/lang/ClassLoader class\n"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/ClassLoader\n"); return NULL; } jmethodID get_system_class_loader_smethod =(*jni_env)->GetStaticMethodID(jni_env, class_loader_class, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); - jthrowable exception = (*jni_env)->ExceptionOccurred(jni_env); - if (NULL != exception) - { - VERBOSE_PRINT("Exception occured: can not get method java.lang.ClassLoader.getSystemClassLoader()\n"); - (*jni_env)->ExceptionClear(jni_env); - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - return NULL; - } - if (NULL == get_system_class_loader_smethod) + if (check_and_clear_exception(jni_env) || NULL == get_system_class_loader_smethod) { - VERBOSE_PRINT("Cannot find java.lang.ClassLoader.getSystemClassLoader()Ljava/lang/ClassLoader;\n"); - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not find method java.lang.ClassLoader.getSystemClassLoader()Ljava/lang/ClassLoader;\n"); + goto get_system_class_loader_cleanup; } - jobject system_class_loader = (*jni_env)->CallStaticObjectMethod(jni_env, class_loader_class, get_system_class_loader_smethod); - exception = (*jni_env)->ExceptionOccurred(jni_env); - if (NULL != exception) + system_class_loader = (*jni_env)->CallStaticObjectMethod(jni_env, class_loader_class, get_system_class_loader_smethod); + if (check_and_clear_exception(jni_env)) { - VERBOSE_PRINT("java.lang.ClassLoader.getSystemClassLoader() thrown an exception\n"); - (*jni_env)->ExceptionClear(jni_env); - (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); - return NULL; + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Exception occurred: Cannot get the system class loader\n"); + goto get_system_class_loader_cleanup; } +get_system_class_loader_cleanup: (*jni_env)->DeleteLocalRef(jni_env, class_loader_class); return system_class_loader; } @@ -1613,12 +1576,12 @@ static char* get_path_to_class( /* class is loaded using boot classloader */ if (class_loader == NULL) { - VERBOSE_PRINT("A class has not been loaded by a ClassLoader. Going to use the system class loader.\n"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": A class has not been loaded by a ClassLoader. Going to use the system class loader.\n"); class_loader = get_system_class_loader(jvmti_env, jni_env); if (NULL == class_loader) { - VERBOSE_PRINT("Cannot get the system class loader."); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Cannot get the system class loader."); return NULL; } } @@ -1642,16 +1605,16 @@ static jclass find_class_in_loaded_class( } jclass class_class = (*jni_env)->FindClass(jni_env, "java/lang/Class"); - if (NULL == class_class) + if (check_and_clear_exception(jni_env) || NULL == class_class) { - VERBOSE_PRINT("Cannot find java/lang/Class class"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/Class\n"); goto find_class_in_loaded_class_cleanup; } jmethodID get_name_method = (*jni_env)->GetMethodID(jni_env, class_class, "getName", "()Ljava/lang/String;"); - if (NULL == get_name_method) + if (check_and_clear_exception(jni_env) || NULL == get_name_method) { - VERBOSE_PRINT("Cannot find java.lang.Class.getName.()Ljava/lang/String;"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/Class.getName()Ljava/lang/String;\n"); (*jni_env)->DeleteLocalRef(jni_env, class_class); goto find_class_in_loaded_class_cleanup; } @@ -1659,8 +1622,9 @@ static jclass find_class_in_loaded_class( for (jint i = 0; NULL == result && i < num_classes; ++i) { jobject class_name = (*jni_env)->CallObjectMethod(jni_env, loaded_classes[i], get_name_method); - if (NULL == class_name) + if (check_and_clear_exception(jni_env) || NULL == class_name) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get name of a loaded class\n"); continue; } @@ -1697,21 +1661,17 @@ static int print_stack_trace_element( { jclass stack_frame_class = (*jni_env)->GetObjectClass(jni_env, stack_frame); jmethodID get_class_name_method = (*jni_env)->GetMethodID(jni_env, stack_frame_class, "getClassName", "()Ljava/lang/String;"); - if (get_class_name_method == NULL) + if (check_and_clear_exception(jni_env) || get_class_name_method == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Frame class).getClassName()Ljava/lang/String;\n"); (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class); return -1; } jstring class_name_of_frame_method = (*jni_env)->CallObjectMethod(jni_env, stack_frame, get_class_name_method); - if ((*jni_env)->ExceptionOccurred(jni_env)) - { - (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class); - (*jni_env)->ExceptionClear(jni_env); - return -1; - } - if (class_name_of_frame_method == NULL) + if (check_and_clear_exception(jni_env) || class_name_of_frame_method == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class name of a class on a frame\n"); (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class); return -1; } @@ -1721,11 +1681,9 @@ static int print_stack_trace_element( jclass class_of_frame_method = (*jni_env)->FindClass(jni_env, cls_name_str); char *class_location = NULL; - if ((*jni_env)->ExceptionOccurred(jni_env)) + if (check_and_clear_exception(jni_env) || NULL == class_of_frame_method) { - VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": FindClass(%s) thrown an exception\n", cls_name_str); - (*jni_env)->ExceptionClear(jni_env); - + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of %s. Try more hard by searching in the loaded classes.\n", cls_name_str); string_replace(cls_name_str, '/', '.'); class_of_frame_method = find_class_in_loaded_class(jvmti_env, jni_env, cls_name_str); string_replace(cls_name_str, '.', '/'); @@ -1753,20 +1711,16 @@ static int print_stack_trace_element( jmethodID to_string_method = (*jni_env)->GetMethodID(jni_env, stack_frame_class, "toString", "()Ljava/lang/String;"); (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class); - if (to_string_method == NULL) + if (check_and_clear_exception(jni_env) || to_string_method == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Frame class).toString()Ljava/lang/String;\n"); return -1; } jobject orig_str = (*jni_env)->CallObjectMethod(jni_env, stack_frame, to_string_method); - if ((*jni_env)->ExceptionOccurred(jni_env)) - { - (*jni_env)->DeleteLocalRef(jni_env, orig_str); - (*jni_env)->ExceptionClear(jni_env); - return -1; - } - if (orig_str == NULL) + if (check_and_clear_exception(jni_env) || NULL == orig_str) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a string representation of a class on a frame\n"); (*jni_env)->DeleteLocalRef(jni_env, orig_str); return -1; } @@ -1801,21 +1755,17 @@ static int print_exception_stack_trace( jclass exception_class = (*jni_env)->GetObjectClass(jni_env, exception); jmethodID to_string_method = (*jni_env)->GetMethodID(jni_env, exception_class, "toString", "()Ljava/lang/String;"); - if (to_string_method == NULL) + if (check_and_clear_exception(jni_env) || to_string_method == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).toString()Ljava/lang/String;\n"); (*jni_env)->DeleteLocalRef(jni_env, exception_class); return -1; } jobject exception_str = (*jni_env)->CallObjectMethod(jni_env, exception, to_string_method); - if ((*jni_env)->ExceptionCheck(jni_env)) - { - (*jni_env)->DeleteLocalRef(jni_env, exception_class); - (*jni_env)->ExceptionClear(jni_env); - return -1; - } - if (exception_str == NULL) + if (check_and_clear_exception(jni_env) || exception_str == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a string representation of a class on a frame\n"); (*jni_env)->DeleteLocalRef(jni_env, exception_class); return -1; } @@ -1840,26 +1790,23 @@ static int print_exception_stack_trace( jmethodID get_stack_trace_method = (*jni_env)->GetMethodID(jni_env, exception_class, "getStackTrace", "()[Ljava/lang/StackTraceElement;"); (*jni_env)->DeleteLocalRef(jni_env, exception_class); - if (get_stack_trace_method == NULL) + if (check_and_clear_exception(jni_env) || get_stack_trace_method == NULL) { - VERBOSE_PRINT("Cannot get getStackTrace() method id"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).getStackTrace()[Ljava/lang/StackTraceElement;\n"); return wrote; } jobject stack_trace_array = (*jni_env)->CallObjectMethod(jni_env, exception, get_stack_trace_method); - if ((*jni_env)->ExceptionCheck(jni_env)) - { - (*jni_env)->ExceptionClear(jni_env); - return wrote; - } - if (stack_trace_array == NULL) + if (check_and_clear_exception(jni_env) || stack_trace_array == NULL) { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a stack trace from an exception object\n"); return wrote; } jint array_size = (*jni_env)->GetArrayLength(jni_env, stack_trace_array); for (jint i = 0; i < array_size; ++i) { + /* Throws only ArrayIndexOutOfBoundsException and this should not happen */ jobject frame_element = (*jni_env)->GetObjectArrayElement(jni_env, stack_trace_array, i); const int frame_wrote = print_stack_trace_element(jvmti_env, @@ -1918,23 +1865,30 @@ static char *generate_thread_stack_trace( wrote += exception_wrote; + /* GetObjectClass() throws nothing */ jclass exception_class = (*jni_env)->GetObjectClass(jni_env, exception); if (NULL == exception_class) { - VERBOSE_PRINT("Cannot get class of an object\n"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Cannot get class of an object\n"); return stack_trace_str; } jmethodID get_cause_method = (*jni_env)->GetMethodID(jni_env, exception_class, "getCause", "()Ljava/lang/Throwable;"); (*jni_env)->DeleteLocalRef(jni_env, exception_class); - if (NULL == get_cause_method) + if (check_and_clear_exception(jni_env) || NULL == get_cause_method) { - VERBOSE_PRINT("Cannot find get an id of getCause()Ljava/lang/Throwable; method\n"); + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).getCause()Ljava/lang/Throwable;\n"); return stack_trace_str; } jobject cause = (*jni_env)->CallObjectMethod(jni_env, exception, get_cause_method); + if (check_and_clear_exception(jni_env)) + { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to get an inner exception of the top most one;\n"); + return stack_trace_str; + } + while (NULL != cause) { if ((size_t)(MAX_STACK_TRACE_STRING_LENGTH - wrote) < (sizeof(CAUSED_STACK_TRACE_HEADER) - 1)) @@ -1965,6 +1919,11 @@ static char *generate_thread_stack_trace( jobject next_cause = (*jni_env)->CallObjectMethod(jni_env, cause, get_cause_method); (*jni_env)->DeleteLocalRef(jni_env, cause); + if (check_and_clear_exception(jni_env)) + { + VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to get an inner exception of another inner one;\n"); + return stack_trace_str; + } cause = next_cause; } @@ -2318,14 +2277,14 @@ static void JNICALL callback_on_exception_catch( } jclass object_class = (*jni_env)->FindClass(jni_env, "java/lang/Object"); - if (NULL == object_class) + if (check_and_clear_exception(jni_env) || NULL == object_class) { VERBOSE_PRINT("Cannot find java/lang/Object class"); goto callback_on_exception_catch_exit; } jmethodID equal_method = (*jni_env)->GetMethodID(jni_env, object_class, "equals", "(Ljava/lang/Object;)Z"); - if (NULL == equal_method) + if (check_and_clear_exception(jni_env) || NULL == equal_method) { VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method"); (*jni_env)->DeleteLocalRef(jni_env, object_class); @@ -2333,8 +2292,12 @@ static void JNICALL callback_on_exception_catch( } jboolean equal_objects = (*jni_env)->CallBooleanMethod(jni_env, exception_object, equal_method, rpt->exception_object); - if (!equal_objects) + if (check_and_clear_exception(jni_env) || !equal_objects) + { + VERBOSE_PRINT("Cannot determine whether the caught exception is also the uncaught exception"); + (*jni_env)->DeleteLocalRef(jni_env, object_class); goto callback_on_exception_catch_exit; + } /* Faster than get()-pop() approach is faster because it is search-and-search-free but * pop()-push() approach is search-free-and-search-malloc diff --git a/src/jthrowable_circular_buf.c b/src/jthrowable_circular_buf.c index e13801c..64f0f30 100644 --- a/src/jthrowable_circular_buf.c +++ b/src/jthrowable_circular_buf.c @@ -162,6 +162,16 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j } jclass object_class = (*buffer->jni_env)->FindClass(buffer->jni_env, "java/lang/Object"); + if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env)) + { + VERBOSE_PRINT("Cannot find java/lang/Object class\n"); +#ifdef VERBOSE + (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env); +#endif + (*buffer->jni_env)->ExceptionClear(buffer->jni_env); + return 1; + } + if (NULL == object_class) { VERBOSE_PRINT("Cannot find java/lang/Object class"); @@ -169,6 +179,16 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j } jmethodID equal_method = (*buffer->jni_env)->GetMethodID(buffer->jni_env, object_class, "equals", "(Ljava/lang/Object;)Z"); + if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env)) + { + VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method\n"); +#ifdef VERBOSE + (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env); +#endif + (*buffer->jni_env)->ExceptionClear(buffer->jni_env); + return 1; + } + if (NULL == equal_method) { VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method"); @@ -182,10 +202,24 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j for (size_t i = rbegin; /* break inside */; i = jthrowable_circular_buf_get_index(buffer, (i - 1))) { VERBOSE_PRINT("Checking next exception object %p\n", (void *)buffer->mem[i]); - if (NULL != buffer->mem[i] && (*buffer->jni_env)->CallBooleanMethod(buffer->jni_env, buffer->mem[i], equal_method, exception)) + if (NULL != buffer->mem[i]) { - *index = i; - return 0; + jboolean equals = (*buffer->jni_env)->CallBooleanMethod(buffer->jni_env, buffer->mem[i], equal_method, exception); + if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env)) + { + VERBOSE_PRINT("Cannot determine whether objects are equal\n"); +#ifdef VERBOSE + (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env); +#endif + (*buffer->jni_env)->ExceptionClear(buffer->jni_env); + return 1; + } + + if (equals) + { + *index = i; + return 0; + } } if (rend == i) -- 1.8.3.1