@@ -20,49 +20,78 @@ JNIEnv *getJNIEnv() {
2020 return pEnv;
2121}
2222
23- // Class fully qualified names
24- const char *CLS_NODE = " org/bblfsh/client/v2/Node" ;
25- const char *CLS_CTX = " org/bblfsh/client/v2/Context" ;
26- const char *CLS_OBJ = " java/lang/Object" ;
27- const char *CLS_RE = " java/lang/RuntimeException" ;
28-
29- const char *CLS_JNODE = " org/bblfsh/client/v2/JNode" ;
30- const char *CLS_JNULL = " org/bblfsh/client/v2/JNull" ;
31- const char *CLS_JSTR = " org/bblfsh/client/v2/JString" ;
32- const char *CLS_JINT = " org/bblfsh/client/v2/JInt" ;
33- const char *CLS_JFLT = " org/bblfsh/client/v2/JFloat" ;
34- const char *CLS_JBOL = " org/bblfsh/client/v2/JBool" ;
35- const char *CLS_JUINT = " org/bblfsh/client/v2/JUint" ;
36- const char *CLS_JARR = " org/bblfsh/client/v2/JArray" ;
37- const char *CLS_JOBJ = " org/bblfsh/client/v2/JObject" ;
38-
39- // Method signatures
40- const char *METHOD_JNODE_KEY_AT = " (I)Ljava/lang/String;" ;
41- const char *METHOD_JNODE_VALUE_AT = " (I)Lorg/bblfsh/client/v2/JNode;" ;
42- const char *METHOD_JOBJ_ADD =
23+ const char CLS_NODE[] = " org/bblfsh/client/v2/Node" ;
24+ const char CLS_CTX[] = " org/bblfsh/client/v2/Context" ;
25+ const char CLS_OBJ[] = " java/lang/Object" ;
26+ const char CLS_RE[] = " java/lang/RuntimeException" ;
27+ const char CLS_JNODE[] = " org/bblfsh/client/v2/JNode" ;
28+ const char CLS_JNULL[] = " org/bblfsh/client/v2/JNull" ;
29+ const char CLS_JSTR[] = " org/bblfsh/client/v2/JString" ;
30+ const char CLS_JINT[] = " org/bblfsh/client/v2/JInt" ;
31+ const char CLS_JFLT[] = " org/bblfsh/client/v2/JFloat" ;
32+ const char CLS_JBOOL[] = " org/bblfsh/client/v2/JBool" ;
33+ const char CLS_JUINT[] = " org/bblfsh/client/v2/JUint" ;
34+ const char CLS_JARR[] = " org/bblfsh/client/v2/JArray" ;
35+ const char CLS_JOBJ[] = " org/bblfsh/client/v2/JObject" ;
36+
37+ const char METHOD_JNODE_KEY_AT[] = " (I)Ljava/lang/String;" ;
38+ const char METHOD_JNODE_VALUE_AT[] = " (I)Lorg/bblfsh/client/v2/JNode;" ;
39+ const char METHOD_JOBJ_ADD[] =
4340 " (Ljava/lang/String;Lorg/bblfsh/client/v2/JNode;)Lscala/collection/"
4441 " mutable/Buffer;" ;
45- const char * METHOD_JARR_ADD =
42+ const char METHOD_JARR_ADD[] =
4643 " (Lorg/bblfsh/client/v2/JNode;)Lscala/collection/mutable/Buffer;" ;
4744
48- const char * METHOD_OBJ_TO_STR = " ()Ljava/lang/String;" ;
45+ const char METHOD_OBJ_TO_STR[] = " ()Ljava/lang/String;" ;
4946
47+ // TODO(bzz): cache classes&methods in JNI_OnLoad should speed this up
5048void checkJvmException (std::string msg) {
5149 JNIEnv *env = getJNIEnv ();
52- if (env->ExceptionCheck ()) {
53- // env->ExceptionDescribe(); // prints to stdout, un-comment for debuging
54- auto err = env->ExceptionOccurred ();
50+ auto err = env->ExceptionOccurred ();
51+ if (err) {
52+ env->ExceptionClear ();
53+
54+ auto exceptionCls = env->FindClass (CLS_RE);
55+ if (env->ExceptionCheck ()) {
56+ env->ExceptionClear ();
57+ env->Throw (env->ExceptionOccurred ());
58+ return ;
59+ }
60+
61+ jclass cls = env->FindClass (CLS_OBJ);
62+ if (env->ExceptionCheck ()) {
63+ env->ExceptionClear ();
64+ env->ThrowNew (
65+ exceptionCls,
66+ msg.append (" - failed to find class " ).append (CLS_OBJ).data ());
67+ return ;
68+ }
69+
70+ jmethodID toString = env->GetMethodID (cls, " toString" , METHOD_OBJ_TO_STR);
71+ if (env->ExceptionCheck ()) {
72+ env->ExceptionClear ();
73+ env->ThrowNew (exceptionCls,
74+ msg.append (" - failed to find method toString" ).data ());
75+ return ;
76+ }
5577
56- jmethodID toString = env->GetMethodID (env->FindClass (CLS_OBJ), " toString" ,
57- METHOD_OBJ_TO_STR);
5878 jstring s = (jstring)env->CallObjectMethod (err, toString);
79+ if (env->ExceptionCheck () || !s) {
80+ env->ThrowNew (exceptionCls,
81+ msg.append (" - failed co call method toString" ).data ());
82+ return ;
83+ }
84+
5985 const char *utf = env->GetStringUTFChars (s, 0 );
6086 env->ReleaseStringUTFChars (s, utf);
6187
62- env->ExceptionClear ();
88+ // new RuntimeException(msg.data(), err)
89+ jmethodID initId = env->GetMethodID (
90+ cls, " <init>" , " (Ljava/lang/String;Ljava/lang/Throwable;)V" );
91+ jthrowable exception = (jthrowable)env->NewObject (
92+ exceptionCls, initId, msg.append (" : " ).append (utf).data (), err);
6393
64- auto exception = env->FindClass (CLS_RE);
65- env->ThrowNew (exception, msg.append (" : " ).append (utf).data ());
94+ env->Throw (exception);
6695 }
6796}
6897
@@ -72,8 +101,10 @@ jobject NewJavaObject(JNIEnv *env, const char *className, const char *initSign,
72101 checkJvmException (std::string (" failed to find a class " ).append (className));
73102
74103 jmethodID initId = env->GetMethodID (cls, " <init>" , initSign);
75- checkJvmException (
76- std::string (" failed to call <inti> constructor for " ).append (className));
104+ checkJvmException (std::string (" failed to call a constructor with signature " )
105+ .append (initSign)
106+ .append (" for the class name " )
107+ .append (className));
77108
78109 va_list varargs;
79110 va_start (varargs, initSign);
@@ -87,7 +118,7 @@ jobject NewJavaObject(JNIEnv *env, const char *className, const char *initSign,
87118
88119jfieldID getField (JNIEnv *env, jobject obj, const char *name) {
89120 jclass cls = env->GetObjectClass (obj);
90- checkJvmException (" failed get an object class " );
121+ checkJvmException (" failed get the class of an object" );
91122
92123 jfieldID jfid = env->GetFieldID (cls, name, " J" );
93124 checkJvmException (std::string (" failed get a field " ).append (name));
@@ -101,7 +132,7 @@ static jmethodID MethodID(JNIEnv *env, const char *method,
101132 checkJvmException (std::string (" failed to find a class " ).append (className));
102133
103134 jmethodID mId = env->GetMethodID (cls, method, signature);
104- checkJvmException (std::string (" failed get a method " )
135+ checkJvmException (std::string (" failed to get method " )
105136 .append (className)
106137 .append (" ." )
107138 .append (method));
@@ -112,13 +143,13 @@ static jmethodID MethodID(JNIEnv *env, const char *method,
112143jint IntMethod (JNIEnv *env, const char *method, const char *signature,
113144 const char *className, const jobject *object) {
114145 jmethodID mId = MethodID (env, method, signature, className);
115- checkJvmException (std::string (" failed get a method " )
146+ checkJvmException (std::string (" failed to get method " )
116147 .append (className)
117148 .append (" ." )
118149 .append (method));
119150
120151 jint res = env->CallIntMethod (*object, mId );
121- checkJvmException (std::string (" failed call a method " )
152+ checkJvmException (std::string (" failed to call method " )
122153 .append (className)
123154 .append (" ." )
124155 .append (method)
@@ -131,7 +162,7 @@ jint IntMethod(JNIEnv *env, const char *method, const char *signature,
131162jobject ObjectMethod (JNIEnv *env, const char *method, const char *signature,
132163 const char *className, const jobject *object, ...) {
133164 jmethodID mId = MethodID (env, method, signature, className);
134- checkJvmException (std::string (" failed get a method " )
165+ checkJvmException (std::string (" failed to get method " )
135166 .append (className)
136167 .append (" ." )
137168 .append (method));
0 commit comments