Blame SOURCES/0026-Surround-all-JNI-calls-in-try-catch-all-block.patch

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