Skip to content

Commit 469dc35

Browse files
committed
Add useful panic messages on missing classes, methods, fields.
1 parent f5dd05d commit 469dc35

File tree

1 file changed

+72
-15
lines changed

1 file changed

+72
-15
lines changed

java-spaghetti/src/env.rs

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,33 +236,90 @@ impl<'env> Env<'env> {
236236
}
237237

238238
unsafe fn require_class_jni(self, class: &CStr) -> jclass {
239-
let class = ((**self.env).v1_2.FindClass)(self.env, class.as_ptr());
240-
assert!(!class.is_null());
241-
class
239+
let res = ((**self.env).v1_2.FindClass)(self.env, class.as_ptr());
240+
if res.is_null() {
241+
((**self.env).v1_2.ExceptionClear)(self.env);
242+
panic!("could not find class {class:?}");
243+
}
244+
res
245+
}
246+
247+
// used only for debugging
248+
unsafe fn get_class_name(self, class: jclass) -> String {
249+
let classclass = self.require_class_jni(c"java/lang/Class");
250+
251+
// don't use self.require_method() here to avoid recursion!
252+
let method = ((**self.env).v1_2.GetMethodID)(
253+
self.env,
254+
classclass,
255+
c"getName".as_ptr(),
256+
c"()Ljava/lang/String;".as_ptr(),
257+
);
258+
if method.is_null() {
259+
((**self.env).v1_2.ExceptionClear)(self.env);
260+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
261+
return "??? (couldn't get class getName method)".to_string();
262+
}
263+
264+
let string = ((**self.env).v1_2.CallObjectMethod)(self.env, class, method);
265+
if string.is_null() {
266+
return "??? (getName returned null string)".to_string();
267+
}
268+
let chars = ((**self.env).v1_2.GetStringUTFChars)(self.env, string, ptr::null_mut());
269+
if chars.is_null() {
270+
((**self.env).v1_2.DeleteLocalRef)(self.env, string);
271+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
272+
return "??? (GetStringUTFChars returned null chars)".to_string();
273+
}
274+
275+
let cchars = CStr::from_ptr(chars);
276+
let res = cchars.to_string_lossy().to_string();
277+
278+
((**self.env).v1_2.ReleaseStringUTFChars)(self.env, string, chars);
279+
((**self.env).v1_2.DeleteLocalRef)(self.env, string);
280+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
281+
282+
res
242283
}
243284

244285
pub unsafe fn require_method(self, class: jclass, method: &CStr, descriptor: &CStr) -> jmethodID {
245-
let method = ((**self.env).v1_2.GetMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
246-
assert!(!method.is_null());
247-
method
286+
let res = ((**self.env).v1_2.GetMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
287+
if res.is_null() {
288+
((**self.env).v1_2.ExceptionClear)(self.env);
289+
let class_name = self.get_class_name(class);
290+
panic!("could not find method {method:?} {descriptor:?} on class {class_name:?}");
291+
}
292+
res
248293
}
249294

250295
pub unsafe fn require_static_method(self, class: jclass, method: &CStr, descriptor: &CStr) -> jmethodID {
251-
let method = ((**self.env).v1_2.GetStaticMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
252-
assert!(!method.is_null());
253-
method
296+
let res = ((**self.env).v1_2.GetStaticMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
297+
if res.is_null() {
298+
((**self.env).v1_2.ExceptionClear)(self.env);
299+
let class_name = self.get_class_name(class);
300+
panic!("could not find static method {method:?} {descriptor:?} on class {class_name:?}");
301+
}
302+
res
254303
}
255304

256305
pub unsafe fn require_field(self, class: jclass, field: &CStr, descriptor: &CStr) -> jfieldID {
257-
let field = ((**self.env).v1_2.GetFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
258-
assert!(!field.is_null());
259-
field
306+
let res = ((**self.env).v1_2.GetFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
307+
if res.is_null() {
308+
((**self.env).v1_2.ExceptionClear)(self.env);
309+
let class_name = self.get_class_name(class);
310+
panic!("could not find field {field:?} {descriptor:?} on class {class_name:?}");
311+
}
312+
res
260313
}
261314

262315
pub unsafe fn require_static_field(self, class: jclass, field: &CStr, descriptor: &CStr) -> jfieldID {
263-
let field = ((**self.env).v1_2.GetStaticFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
264-
assert!(!field.is_null());
265-
field
316+
let res = ((**self.env).v1_2.GetStaticFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
317+
if res.is_null() {
318+
((**self.env).v1_2.ExceptionClear)(self.env);
319+
let class_name = self.get_class_name(class);
320+
panic!("could not find static field {field:?} {descriptor:?} on class {class_name:?}");
321+
}
322+
res
266323
}
267324

268325
// Multi-Query Methods

0 commit comments

Comments
 (0)