Skip to content

Commit afabe62

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

File tree

1 file changed

+59
-5
lines changed

1 file changed

+59
-5
lines changed

java-spaghetti/src/env.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,31 +237,85 @@ impl<'env> Env<'env> {
237237

238238
unsafe fn require_class_jni(self, class: &CStr) -> jclass {
239239
let class = ((**self.env).v1_2.FindClass)(self.env, class.as_ptr());
240-
assert!(!class.is_null());
240+
if class.is_null() {
241+
panic!("could not find class {class:?}");
242+
}
241243
class
242244
}
243245

246+
// used only for debugging
247+
unsafe fn get_class_name(self, class: jclass) -> String {
248+
let classclass = self.require_class_jni(c"java/lang/Class");
249+
if classclass.is_null() {
250+
return "??? (couldn't get class)".to_string();
251+
}
252+
253+
// don't use self.require_method() here to avoid recursion!
254+
let method = ((**self.env).v1_2.GetMethodID)(
255+
self.env,
256+
classclass,
257+
c"getName".as_ptr(),
258+
c"()Ljava/lang/String;".as_ptr(),
259+
);
260+
if method.is_null() {
261+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
262+
return "??? (couldn't get class getName method)".to_string();
263+
}
264+
265+
let string = ((**self.env).v1_2.CallObjectMethod)(self.env, class, method);
266+
if string.is_null() {
267+
return "??? (getName returned null string)".to_string();
268+
}
269+
let chars = ((**self.env).v1_2.GetStringUTFChars)(self.env, string, ptr::null_mut());
270+
if chars.is_null() {
271+
((**self.env).v1_2.DeleteLocalRef)(self.env, string);
272+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
273+
return "??? (GetStringUTFChars returned null chars)".to_string();
274+
}
275+
276+
let cchars = CStr::from_ptr(chars);
277+
let res = cchars.to_string_lossy().to_string();
278+
279+
((**self.env).v1_2.ReleaseStringUTFChars)(self.env, string, chars);
280+
((**self.env).v1_2.DeleteLocalRef)(self.env, string);
281+
((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
282+
283+
res
284+
}
285+
244286
pub unsafe fn require_method(self, class: jclass, method: &CStr, descriptor: &CStr) -> jmethodID {
245287
let method = ((**self.env).v1_2.GetMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
246-
assert!(!method.is_null());
288+
if method.is_null() {
289+
let class_name = self.get_class_name(class);
290+
panic!("could not find method {method:?} {descriptor:?} on class {class_name:?}");
291+
}
247292
method
248293
}
249294

250295
pub unsafe fn require_static_method(self, class: jclass, method: &CStr, descriptor: &CStr) -> jmethodID {
251296
let method = ((**self.env).v1_2.GetStaticMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
252-
assert!(!method.is_null());
297+
if method.is_null() {
298+
let class_name = self.get_class_name(class);
299+
panic!("could not find static method {method:?} {descriptor:?} on class {class_name:?}");
300+
}
253301
method
254302
}
255303

256304
pub unsafe fn require_field(self, class: jclass, field: &CStr, descriptor: &CStr) -> jfieldID {
257305
let field = ((**self.env).v1_2.GetFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
258-
assert!(!field.is_null());
306+
if field.is_null() {
307+
let class_name = self.get_class_name(class);
308+
panic!("could not find field {field:?} {descriptor:?} on class {class_name:?}");
309+
}
259310
field
260311
}
261312

262313
pub unsafe fn require_static_field(self, class: jclass, field: &CStr, descriptor: &CStr) -> jfieldID {
263314
let field = ((**self.env).v1_2.GetStaticFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
264-
assert!(!field.is_null());
315+
if field.is_null() {
316+
let class_name = self.get_class_name(class);
317+
panic!("could not find static field {field:?} {descriptor:?} on class {class_name:?}");
318+
}
265319
field
266320
}
267321

0 commit comments

Comments
 (0)