2
0

java_support.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2013 Konstantin Mosesov
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * This file is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. *
  14. * This file is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. #include <libgen.h>
  25. #include "../../str.h"
  26. #include "../../sr_module.h"
  27. #include <jni.h>
  28. #include "global.h"
  29. #include "utils.h"
  30. #include "java_mod.h"
  31. #include "java_iface.h"
  32. #include "java_support.h"
  33. static char *_append_exception_trace_messages(char *msg_str, jthrowable a_exception, jmethodID a_mid_throwable_getCause, jmethodID a_mid_throwable_getStackTrace, jmethodID a_mid_throwable_toString, jmethodID a_mid_frame_toString)
  34. {
  35. jobjectArray frames;
  36. jsize frames_length, i;
  37. jstring msg_obj;
  38. jobject frame;
  39. jthrowable cause;
  40. jclass exClass;
  41. jmethodID mid;
  42. jboolean isCopy;
  43. const char *tmpbuf;
  44. // Get the array of StackTraceElements.
  45. frames = (jobjectArray) (*env)->CallObjectMethod(env, a_exception, a_mid_throwable_getStackTrace);
  46. if (!frames)
  47. {
  48. exClass = (*env)->GetObjectClass(env, a_exception);
  49. mid = (*env)->GetMethodID(env, exClass, "toString", "()Ljava/lang/String;");
  50. msg_obj = (jstring) (*env)->CallObjectMethod(env, a_exception, mid);
  51. isCopy = JNI_FALSE;
  52. tmpbuf = (*env)->GetStringUTFChars(env, msg_obj, &isCopy);
  53. strcat(msg_str, tmpbuf);
  54. strcat(msg_str, "\n <<No stacktrace available>>");
  55. (*env)->ReleaseStringUTFChars(env, msg_obj, tmpbuf);
  56. (*env)->DeleteLocalRef(env, msg_obj);
  57. return msg_str;
  58. }
  59. else
  60. {
  61. frames_length = (*env)->GetArrayLength(env, frames);
  62. }
  63. // Add Throwable.toString() before descending stack trace messages.
  64. if (frames != 0)
  65. {
  66. msg_obj = (jstring) (*env)->CallObjectMethod(env, a_exception, a_mid_throwable_toString);
  67. tmpbuf = (*env)->GetStringUTFChars(env, msg_obj, 0);
  68. strcat(msg_str, "Exception in thread \"main\" ");
  69. strcat(msg_str, tmpbuf);
  70. (*env)->ReleaseStringUTFChars(env, msg_obj, tmpbuf);
  71. (*env)->DeleteLocalRef(env, msg_obj);
  72. }
  73. // Append stack trace messages if there are any.
  74. if (frames_length > 0)
  75. {
  76. for (i=0; i<frames_length; i++)
  77. {
  78. // Get the string returned from the 'toString()'
  79. // method of the next frame and append it to
  80. // the error message.
  81. frame = (*env)->GetObjectArrayElement(env, frames, i);
  82. msg_obj = (jstring) (*env)->CallObjectMethod(env, frame, a_mid_frame_toString);
  83. tmpbuf = (*env)->GetStringUTFChars(env, msg_obj, 0);
  84. strcat(msg_str, "\n at ");
  85. strcat(msg_str, tmpbuf);
  86. (*env)->ReleaseStringUTFChars(env, msg_obj, tmpbuf);
  87. (*env)->DeleteLocalRef(env, msg_obj);
  88. (*env)->DeleteLocalRef(env, frame);
  89. }
  90. }
  91. else
  92. {
  93. strcat(msg_str, "\n <<No stacktrace available>>");
  94. }
  95. // If 'a_exception' has a cause then append the
  96. // stack trace messages from the cause.
  97. if (frames != 0)
  98. {
  99. cause = (jthrowable) (*env)->CallObjectMethod(env, a_exception, a_mid_throwable_getCause);
  100. if (cause != 0)
  101. {
  102. tmpbuf = _append_exception_trace_messages(msg_str, cause, a_mid_throwable_getCause, a_mid_throwable_getStackTrace, a_mid_throwable_toString, a_mid_frame_toString);
  103. strcat(msg_str, tmpbuf);
  104. }
  105. }
  106. if (msg_str != NULL)
  107. return strdup(msg_str);
  108. else
  109. return NULL;
  110. }
  111. void handle_exception(void)
  112. {
  113. char *error_msg = NULL;
  114. char msg_str[8192];
  115. jthrowable exception;
  116. jclass throwable_class, frame_class;
  117. jmethodID mid_throwable_getCause, mid_throwable_getStackTrace;
  118. jmethodID mid_throwable_toString, mid_frame_toString;
  119. if (!(*env)->ExceptionCheck(env))
  120. return;
  121. memset(&msg_str, 0, sizeof(msg_str));
  122. // Get the exception and clear as no
  123. // JNI calls can be made while an exception exists.
  124. exception = (*env)->ExceptionOccurred(env);
  125. if (exception)
  126. {
  127. // (*env)->ExceptionDescribe(env);
  128. (*env)->ExceptionClear(env);
  129. throwable_class = (*env)->FindClass(env, "java/lang/Throwable");
  130. mid_throwable_getCause = (*env)->GetMethodID(env, throwable_class, "getCause", "()Ljava/lang/Throwable;");
  131. mid_throwable_getStackTrace = (*env)->GetMethodID(env, throwable_class, "getStackTrace", "()[Ljava/lang/StackTraceElement;");
  132. mid_throwable_toString = (*env)->GetMethodID(env, throwable_class, "toString", "()Ljava/lang/String;");
  133. frame_class = (*env)->FindClass(env, "java/lang/StackTraceElement");
  134. mid_frame_toString = (*env)->GetMethodID(env, frame_class, "toString", "()Ljava/lang/String;");
  135. error_msg = _append_exception_trace_messages(msg_str, exception, mid_throwable_getCause, mid_throwable_getStackTrace, mid_throwable_toString, mid_frame_toString);
  136. (*env)->DeleteLocalRef(env, exception);
  137. }
  138. LM_ERR("%s: Exception:\n%s\n", APP_NAME, error_msg == NULL ? "(no info)" : error_msg);
  139. }
  140. void ThrowNewException(JNIEnv *env, char *fmt, ...)
  141. {
  142. va_list ap;
  143. char buf[1024];
  144. memset(buf, 0, sizeof(char));
  145. va_start(ap, fmt);
  146. vsnprintf(buf, 1024, fmt, ap);
  147. va_end(ap);
  148. (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), buf);
  149. }
  150. void handle_VM_init_failure(int res)
  151. {
  152. switch(res)
  153. {
  154. case -1:
  155. LM_ERR("%s: Couldn't initialize Java VM: unknown error\n", APP_NAME);
  156. break;
  157. case -2:
  158. LM_ERR("%s: Couldn't initialize Java VM: thread detached from the VM\n", APP_NAME);
  159. break;
  160. case -3:
  161. LM_ERR("%s: Couldn't initialize Java VM: JNI version error\n", APP_NAME);
  162. break;
  163. case -4:
  164. LM_ERR("%s: Couldn't initialize Java VM: not enough memory\n", APP_NAME);
  165. break;
  166. case -5:
  167. LM_ERR("%s: Couldn't initialize Java VM: VM already created\n", APP_NAME);
  168. break;
  169. case -6:
  170. LM_ERR("%s: Couldn't initialize Java VM: invalid arguments\n", APP_NAME);
  171. break;
  172. default:
  173. LM_ERR("%s: Couldn't initialize Java VM. Error code: %d\n", APP_NAME, res);
  174. break;
  175. }
  176. }