java_support.c 6.5 KB

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