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