@@ -20,49 +20,78 @@ JNIEnv *getJNIEnv() {
20
20
return pEnv;
21
21
}
22
22
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[] =
43
40
" (Ljava/lang/String;Lorg/bblfsh/client/v2/JNode;)Lscala/collection/"
44
41
" mutable/Buffer;" ;
45
- const char * METHOD_JARR_ADD =
42
+ const char METHOD_JARR_ADD[] =
46
43
" (Lorg/bblfsh/client/v2/JNode;)Lscala/collection/mutable/Buffer;" ;
47
44
48
- const char * METHOD_OBJ_TO_STR = " ()Ljava/lang/String;" ;
45
+ const char METHOD_OBJ_TO_STR[] = " ()Ljava/lang/String;" ;
49
46
47
+ // TODO(bzz): cache classes&methods in JNI_OnLoad should speed this up
50
48
void checkJvmException (std::string msg) {
51
49
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
+ }
55
77
56
- jmethodID toString = env->GetMethodID (env->FindClass (CLS_OBJ), " toString" ,
57
- METHOD_OBJ_TO_STR);
58
78
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
+
59
85
const char *utf = env->GetStringUTFChars (s, 0 );
60
86
env->ReleaseStringUTFChars (s, utf);
61
87
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);
63
93
64
- auto exception = env->FindClass (CLS_RE);
65
- env->ThrowNew (exception , msg.append (" : " ).append (utf).data ());
94
+ env->Throw (exception );
66
95
}
67
96
}
68
97
@@ -72,8 +101,10 @@ jobject NewJavaObject(JNIEnv *env, const char *className, const char *initSign,
72
101
checkJvmException (std::string (" failed to find a class " ).append (className));
73
102
74
103
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));
77
108
78
109
va_list varargs;
79
110
va_start (varargs, initSign);
@@ -87,7 +118,7 @@ jobject NewJavaObject(JNIEnv *env, const char *className, const char *initSign,
87
118
88
119
jfieldID getField (JNIEnv *env, jobject obj, const char *name) {
89
120
jclass cls = env->GetObjectClass (obj);
90
- checkJvmException (" failed get an object class " );
121
+ checkJvmException (" failed get the class of an object" );
91
122
92
123
jfieldID jfid = env->GetFieldID (cls, name, " J" );
93
124
checkJvmException (std::string (" failed get a field " ).append (name));
@@ -101,7 +132,7 @@ static jmethodID MethodID(JNIEnv *env, const char *method,
101
132
checkJvmException (std::string (" failed to find a class " ).append (className));
102
133
103
134
jmethodID mId = env->GetMethodID (cls, method, signature);
104
- checkJvmException (std::string (" failed get a method " )
135
+ checkJvmException (std::string (" failed to get method " )
105
136
.append (className)
106
137
.append (" ." )
107
138
.append (method));
@@ -112,13 +143,13 @@ static jmethodID MethodID(JNIEnv *env, const char *method,
112
143
jint IntMethod (JNIEnv *env, const char *method, const char *signature,
113
144
const char *className, const jobject *object) {
114
145
jmethodID mId = MethodID (env, method, signature, className);
115
- checkJvmException (std::string (" failed get a method " )
146
+ checkJvmException (std::string (" failed to get method " )
116
147
.append (className)
117
148
.append (" ." )
118
149
.append (method));
119
150
120
151
jint res = env->CallIntMethod (*object, mId );
121
- checkJvmException (std::string (" failed call a method " )
152
+ checkJvmException (std::string (" failed to call method " )
122
153
.append (className)
123
154
.append (" ." )
124
155
.append (method)
@@ -131,7 +162,7 @@ jint IntMethod(JNIEnv *env, const char *method, const char *signature,
131
162
jobject ObjectMethod (JNIEnv *env, const char *method, const char *signature,
132
163
const char *className, const jobject *object, ...) {
133
164
jmethodID mId = MethodID (env, method, signature, className);
134
- checkJvmException (std::string (" failed get a method " )
165
+ checkJvmException (std::string (" failed to get method " )
135
166
.append (className)
136
167
.append (" ." )
137
168
.append (method));
0 commit comments