1use crate::{AsArg, Local, Ref, ReferenceType, StringChars, ThrowableType, VM};
2use jni_sys::*;
3use std::{
4 ffi::CStr,
5 marker::PhantomData,
6 ptr::{self, null_mut},
7 sync::{
8 OnceLock,
9 atomic::{AtomicPtr, Ordering},
10 },
11};
12
13#[repr(transparent)]
65#[derive(Copy, Clone)]
66pub struct Env<'env> {
67 env: *mut JNIEnv,
68 pd: PhantomData<&'env mut JNIEnv>,
69}
70
71static CLASS_LOADER: AtomicPtr<_jobject> = AtomicPtr::new(null_mut());
72
73#[allow(clippy::missing_safety_doc)]
74#[allow(unsafe_op_in_unsafe_fn)]
75impl<'env> Env<'env> {
76 pub unsafe fn from_raw(ptr: *mut JNIEnv) -> Self {
77 Self {
78 env: ptr,
79 pd: PhantomData,
80 }
81 }
82
83 pub fn as_raw(&self) -> *mut JNIEnv {
84 self.env
85 }
86
87 pub fn vm(&self) -> VM {
88 let jni_env = self.as_raw();
89 let mut vm = null_mut();
90 let err = unsafe { ((**jni_env).v1_2.GetJavaVM)(jni_env, &mut vm) };
91 assert_eq!(err, JNI_OK);
92 assert_ne!(vm, null_mut());
93 unsafe { VM::from_raw(vm) }
94 }
95
96 pub unsafe fn new_string(self, chars: *const jchar, len: jsize) -> jstring {
99 let result = ((**self.env).v1_2.NewString)(self.env, chars as *const _, len);
100 assert!(!result.is_null());
101 result
102 }
103
104 pub unsafe fn get_string_length(self, string: jstring) -> jsize {
105 ((**self.env).v1_2.GetStringLength)(self.env, string)
106 }
107
108 pub unsafe fn get_string_chars(self, string: jstring) -> *const jchar {
109 ((**self.env).v1_2.GetStringChars)(self.env, string, null_mut()) as *const _
110 }
111
112 pub unsafe fn release_string_chars(self, string: jstring, chars: *const jchar) {
113 ((**self.env).v1_2.ReleaseStringChars)(self.env, string, chars as *const _)
114 }
115
116 pub unsafe fn set_class_loader(classloader: jobject) {
143 CLASS_LOADER.store(classloader, Ordering::Relaxed);
144 }
145
146 pub(crate) fn exception_check<E: ThrowableType>(self) -> Result<(), Local<'env, E>> {
153 unsafe {
154 let exception = ((**self.env).v1_2.ExceptionOccurred)(self.env);
155 if exception.is_null() {
156 Ok(())
157 } else {
158 ((**self.env).v1_2.ExceptionClear)(self.env);
159 Err(Local::from_raw(self, exception))
160 }
161 }
162 }
163
164 unsafe fn exception_to_string(self, exception: jobject) -> String {
165 static METHOD_GET_MESSAGE: OnceLock<usize> = OnceLock::new();
166 let throwable_get_message = *METHOD_GET_MESSAGE.get_or_init(|| {
167 let throwable_class = self.require_class_jni(c"java/lang/Throwable");
169 let method =
170 self.require_method(throwable_class, c"getMessage", c"()Ljava/lang/String;");
171 ((**self.env).v1_2.DeleteLocalRef)(self.env, throwable_class);
172 method.addr()
173 }) as jmethodID; let message = ((**self.env).v1_2.CallObjectMethodA)(
176 self.env,
177 exception,
178 throwable_get_message,
179 ptr::null_mut(),
180 );
181 let e2: *mut _jobject = ((**self.env).v1_2.ExceptionOccurred)(self.env);
182 if !e2.is_null() {
183 ((**self.env).v1_2.ExceptionClear)(self.env);
184 panic!("exception happened calling Throwable.getMessage()");
185 }
186
187 StringChars::from_env_jstring(self, message).to_string_lossy()
188 }
189
190 pub unsafe fn require_class(self, class: &CStr) -> jclass {
192 let c = ((**self.env).v1_2.FindClass)(self.env, class.as_ptr());
194 let exception: *mut _jobject = ((**self.env).v1_2.ExceptionOccurred)(self.env);
195 if !exception.is_null() {
196 ((**self.env).v1_2.ExceptionClear)(self.env);
197 }
198 if !c.is_null() {
199 return c;
200 }
201
202 let classloader = CLASS_LOADER.load(Ordering::Relaxed);
204 if !classloader.is_null() {
205 let chars = class
206 .to_str()
207 .unwrap()
208 .replace('/', ".")
209 .encode_utf16()
210 .collect::<Vec<_>>();
211 let string = unsafe { self.new_string(chars.as_ptr(), chars.len() as jsize) };
212
213 static CL_METHOD: OnceLock<usize> = OnceLock::new();
214 let cl_method = *CL_METHOD.get_or_init(|| {
215 let cl_class = self.require_class_jni(c"java/lang/ClassLoader");
218 let cl_method = self.require_method(
219 cl_class,
220 c"loadClass",
221 c"(Ljava/lang/String;)Ljava/lang/Class;",
222 );
223 ((**self.env).v1_2.DeleteLocalRef)(self.env, cl_class);
224 cl_method.addr()
225 }) as jmethodID; let args = [jvalue { l: string }];
228 let result: *mut _jobject = ((**self.env).v1_2.CallObjectMethodA)(
229 self.env,
230 classloader,
231 cl_method,
232 args.as_ptr(),
233 );
234 let exception: *mut _jobject = ((**self.env).v1_2.ExceptionOccurred)(self.env);
235 if !exception.is_null() {
236 ((**self.env).v1_2.ExceptionClear)(self.env);
237 panic!(
238 "exception happened calling loadClass(): {}",
239 self.exception_to_string(exception)
240 );
241 } else if result.is_null() {
242 panic!("loadClass() returned null");
243 }
244
245 ((**self.env).v1_2.DeleteLocalRef)(self.env, string);
246
247 return result as jclass;
248 }
249
250 panic!("couldn't load class {class:?}");
252 }
253
254 unsafe fn require_class_jni(self, class: &CStr) -> jclass {
255 let res = ((**self.env).v1_2.FindClass)(self.env, class.as_ptr());
256 if res.is_null() {
257 ((**self.env).v1_2.ExceptionClear)(self.env);
258 panic!("could not find class {class:?}");
259 }
260 res
261 }
262
263 unsafe fn get_class_name(self, class: jclass) -> String {
265 let classclass = self.require_class_jni(c"java/lang/Class");
266
267 let method = ((**self.env).v1_2.GetMethodID)(
269 self.env,
270 classclass,
271 c"getName".as_ptr(),
272 c"()Ljava/lang/String;".as_ptr(),
273 );
274 if method.is_null() {
275 ((**self.env).v1_2.ExceptionClear)(self.env);
276 ((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
277 return "??? (couldn't get class getName method)".to_string();
278 }
279
280 let string = ((**self.env).v1_2.CallObjectMethod)(self.env, class, method);
282 if string.is_null() {
283 return "??? (getName returned null string)".to_string();
284 }
285 let chars = ((**self.env).v1_2.GetStringUTFChars)(self.env, string, ptr::null_mut());
286 if chars.is_null() {
287 ((**self.env).v1_2.DeleteLocalRef)(self.env, string);
288 ((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
289 return "??? (GetStringUTFChars returned null chars)".to_string();
290 }
291
292 let cchars = CStr::from_ptr(chars);
293 let res = cchars.to_string_lossy().to_string();
294
295 ((**self.env).v1_2.ReleaseStringUTFChars)(self.env, string, chars);
296 ((**self.env).v1_2.DeleteLocalRef)(self.env, string);
297 ((**self.env).v1_2.DeleteLocalRef)(self.env, classclass);
298
299 res
300 }
301
302 pub unsafe fn require_method(
303 self,
304 class: jclass,
305 method: &CStr,
306 descriptor: &CStr,
307 ) -> jmethodID {
308 let res =
309 ((**self.env).v1_2.GetMethodID)(self.env, class, method.as_ptr(), descriptor.as_ptr());
310 if res.is_null() {
311 ((**self.env).v1_2.ExceptionClear)(self.env);
312 let class_name = self.get_class_name(class);
313 panic!("could not find method {method:?} {descriptor:?} on class {class_name:?}");
314 }
315 res
316 }
317
318 pub unsafe fn require_static_method(
319 self,
320 class: jclass,
321 method: &CStr,
322 descriptor: &CStr,
323 ) -> jmethodID {
324 let res = ((**self.env).v1_2.GetStaticMethodID)(
325 self.env,
326 class,
327 method.as_ptr(),
328 descriptor.as_ptr(),
329 );
330 if res.is_null() {
331 ((**self.env).v1_2.ExceptionClear)(self.env);
332 let class_name = self.get_class_name(class);
333 panic!(
334 "could not find static method {method:?} {descriptor:?} on class {class_name:?}"
335 );
336 }
337 res
338 }
339
340 pub unsafe fn require_field(self, class: jclass, field: &CStr, descriptor: &CStr) -> jfieldID {
341 let res =
342 ((**self.env).v1_2.GetFieldID)(self.env, class, field.as_ptr(), descriptor.as_ptr());
343 if res.is_null() {
344 ((**self.env).v1_2.ExceptionClear)(self.env);
345 let class_name = self.get_class_name(class);
346 panic!("could not find field {field:?} {descriptor:?} on class {class_name:?}");
347 }
348 res
349 }
350
351 pub unsafe fn require_static_field(
352 self,
353 class: jclass,
354 field: &CStr,
355 descriptor: &CStr,
356 ) -> jfieldID {
357 let res = ((**self.env).v1_2.GetStaticFieldID)(
358 self.env,
359 class,
360 field.as_ptr(),
361 descriptor.as_ptr(),
362 );
363 if res.is_null() {
364 ((**self.env).v1_2.ExceptionClear)(self.env);
365 let class_name = self.get_class_name(class);
366 panic!("could not find static field {field:?} {descriptor:?} on class {class_name:?}");
367 }
368 res
369 }
370
371 pub unsafe fn require_class_method(
375 self,
376 class: &CStr,
377 method: &CStr,
378 descriptor: &CStr,
379 ) -> (jclass, jmethodID) {
380 let class = self.require_class(class);
381 (class, self.require_method(class, method, descriptor))
382 }
383
384 pub unsafe fn require_class_static_method(
385 self,
386 class: &CStr,
387 method: &CStr,
388 descriptor: &CStr,
389 ) -> (jclass, jmethodID) {
390 let class = self.require_class(class);
391 (class, self.require_static_method(class, method, descriptor))
392 }
393
394 pub unsafe fn require_class_field(
395 self,
396 class: &CStr,
397 method: &CStr,
398 descriptor: &CStr,
399 ) -> (jclass, jfieldID) {
400 let class = self.require_class(class);
401 (class, self.require_field(class, method, descriptor))
402 }
403
404 pub unsafe fn require_class_static_field(
405 self,
406 class: &CStr,
407 method: &CStr,
408 descriptor: &CStr,
409 ) -> (jclass, jfieldID) {
410 let class = self.require_class(class);
411 (class, self.require_static_field(class, method, descriptor))
412 }
413
414 pub unsafe fn new_object_a<R: ReferenceType, E: ThrowableType>(
417 self,
418 class: jclass,
419 method: jmethodID,
420 args: *const jvalue,
421 ) -> Result<Local<'env, R>, Local<'env, E>> {
422 let result = ((**self.env).v1_2.NewObjectA)(self.env, class, method, args);
423 self.exception_check()?;
424 assert!(!result.is_null());
425 Ok(Local::from_raw(self, result))
426 }
427
428 pub unsafe fn call_object_method_a<R: ReferenceType, E: ThrowableType>(
431 self,
432 this: jobject,
433 method: jmethodID,
434 args: *const jvalue,
435 ) -> Result<Option<Local<'env, R>>, Local<'env, E>> {
436 let result = ((**self.env).v1_2.CallObjectMethodA)(self.env, this, method, args);
437 self.exception_check()?;
438 if result.is_null() {
439 Ok(None)
440 } else {
441 Ok(Some(Local::from_raw(self, result)))
442 }
443 }
444
445 pub unsafe fn call_boolean_method_a<E: ThrowableType>(
446 self,
447 this: jobject,
448 method: jmethodID,
449 args: *const jvalue,
450 ) -> Result<bool, Local<'env, E>> {
451 let result = ((**self.env).v1_2.CallBooleanMethodA)(self.env, this, method, args);
452 self.exception_check()?;
453 Ok(result != JNI_FALSE)
454 }
455
456 pub unsafe fn call_byte_method_a<E: ThrowableType>(
457 self,
458 this: jobject,
459 method: jmethodID,
460 args: *const jvalue,
461 ) -> Result<jbyte, Local<'env, E>> {
462 let result = ((**self.env).v1_2.CallByteMethodA)(self.env, this, method, args);
463 self.exception_check()?;
464 Ok(result)
465 }
466
467 pub unsafe fn call_char_method_a<E: ThrowableType>(
468 self,
469 this: jobject,
470 method: jmethodID,
471 args: *const jvalue,
472 ) -> Result<jchar, Local<'env, E>> {
473 let result = ((**self.env).v1_2.CallCharMethodA)(self.env, this, method, args);
474 self.exception_check()?;
475 Ok(result)
476 }
477
478 pub unsafe fn call_short_method_a<E: ThrowableType>(
479 self,
480 this: jobject,
481 method: jmethodID,
482 args: *const jvalue,
483 ) -> Result<jshort, Local<'env, E>> {
484 let result = ((**self.env).v1_2.CallShortMethodA)(self.env, this, method, args);
485 self.exception_check()?;
486 Ok(result)
487 }
488
489 pub unsafe fn call_int_method_a<E: ThrowableType>(
490 self,
491 this: jobject,
492 method: jmethodID,
493 args: *const jvalue,
494 ) -> Result<jint, Local<'env, E>> {
495 let result = ((**self.env).v1_2.CallIntMethodA)(self.env, this, method, args);
496 self.exception_check()?;
497 Ok(result)
498 }
499
500 pub unsafe fn call_long_method_a<E: ThrowableType>(
501 self,
502 this: jobject,
503 method: jmethodID,
504 args: *const jvalue,
505 ) -> Result<jlong, Local<'env, E>> {
506 let result = ((**self.env).v1_2.CallLongMethodA)(self.env, this, method, args);
507 self.exception_check()?;
508 Ok(result)
509 }
510
511 pub unsafe fn call_float_method_a<E: ThrowableType>(
512 self,
513 this: jobject,
514 method: jmethodID,
515 args: *const jvalue,
516 ) -> Result<jfloat, Local<'env, E>> {
517 let result = ((**self.env).v1_2.CallFloatMethodA)(self.env, this, method, args);
518 self.exception_check()?;
519 Ok(result)
520 }
521
522 pub unsafe fn call_double_method_a<E: ThrowableType>(
523 self,
524 this: jobject,
525 method: jmethodID,
526 args: *const jvalue,
527 ) -> Result<jdouble, Local<'env, E>> {
528 let result = ((**self.env).v1_2.CallDoubleMethodA)(self.env, this, method, args);
529 self.exception_check()?;
530 Ok(result)
531 }
532
533 pub unsafe fn call_void_method_a<E: ThrowableType>(
534 self,
535 this: jobject,
536 method: jmethodID,
537 args: *const jvalue,
538 ) -> Result<(), Local<'env, E>> {
539 ((**self.env).v1_2.CallVoidMethodA)(self.env, this, method, args);
540 self.exception_check()
541 }
542
543 pub unsafe fn call_static_object_method_a<R: ReferenceType, E: ThrowableType>(
546 self,
547 class: jclass,
548 method: jmethodID,
549 args: *const jvalue,
550 ) -> Result<Option<Local<'env, R>>, Local<'env, E>> {
551 let result = ((**self.env).v1_2.CallStaticObjectMethodA)(self.env, class, method, args);
552 self.exception_check()?;
553 if result.is_null() {
554 Ok(None)
555 } else {
556 Ok(Some(Local::from_raw(self, result)))
557 }
558 }
559
560 pub unsafe fn call_static_boolean_method_a<E: ThrowableType>(
561 self,
562 class: jclass,
563 method: jmethodID,
564 args: *const jvalue,
565 ) -> Result<bool, Local<'env, E>> {
566 let result = ((**self.env).v1_2.CallStaticBooleanMethodA)(self.env, class, method, args);
567 self.exception_check()?;
568 Ok(result != JNI_FALSE)
569 }
570
571 pub unsafe fn call_static_byte_method_a<E: ThrowableType>(
572 self,
573 class: jclass,
574 method: jmethodID,
575 args: *const jvalue,
576 ) -> Result<jbyte, Local<'env, E>> {
577 let result = ((**self.env).v1_2.CallStaticByteMethodA)(self.env, class, method, args);
578 self.exception_check()?;
579 Ok(result)
580 }
581
582 pub unsafe fn call_static_char_method_a<E: ThrowableType>(
583 self,
584 class: jclass,
585 method: jmethodID,
586 args: *const jvalue,
587 ) -> Result<jchar, Local<'env, E>> {
588 let result = ((**self.env).v1_2.CallStaticCharMethodA)(self.env, class, method, args);
589 self.exception_check()?;
590 Ok(result)
591 }
592
593 pub unsafe fn call_static_short_method_a<E: ThrowableType>(
594 self,
595 class: jclass,
596 method: jmethodID,
597 args: *const jvalue,
598 ) -> Result<jshort, Local<'env, E>> {
599 let result = ((**self.env).v1_2.CallStaticShortMethodA)(self.env, class, method, args);
600 self.exception_check()?;
601 Ok(result)
602 }
603
604 pub unsafe fn call_static_int_method_a<E: ThrowableType>(
605 self,
606 class: jclass,
607 method: jmethodID,
608 args: *const jvalue,
609 ) -> Result<jint, Local<'env, E>> {
610 let result = ((**self.env).v1_2.CallStaticIntMethodA)(self.env, class, method, args);
611 self.exception_check()?;
612 Ok(result)
613 }
614
615 pub unsafe fn call_static_long_method_a<E: ThrowableType>(
616 self,
617 class: jclass,
618 method: jmethodID,
619 args: *const jvalue,
620 ) -> Result<jlong, Local<'env, E>> {
621 let result = ((**self.env).v1_2.CallStaticLongMethodA)(self.env, class, method, args);
622 self.exception_check()?;
623 Ok(result)
624 }
625
626 pub unsafe fn call_static_float_method_a<E: ThrowableType>(
627 self,
628 class: jclass,
629 method: jmethodID,
630 args: *const jvalue,
631 ) -> Result<jfloat, Local<'env, E>> {
632 let result = ((**self.env).v1_2.CallStaticFloatMethodA)(self.env, class, method, args);
633 self.exception_check()?;
634 Ok(result)
635 }
636
637 pub unsafe fn call_static_double_method_a<E: ThrowableType>(
638 self,
639 class: jclass,
640 method: jmethodID,
641 args: *const jvalue,
642 ) -> Result<jdouble, Local<'env, E>> {
643 let result = ((**self.env).v1_2.CallStaticDoubleMethodA)(self.env, class, method, args);
644 self.exception_check()?;
645 Ok(result)
646 }
647
648 pub unsafe fn call_static_void_method_a<E: ThrowableType>(
649 self,
650 class: jclass,
651 method: jmethodID,
652 args: *const jvalue,
653 ) -> Result<(), Local<'env, E>> {
654 ((**self.env).v1_2.CallStaticVoidMethodA)(self.env, class, method, args);
655 self.exception_check()
656 }
657
658 pub unsafe fn get_object_field<R: ReferenceType>(
661 self,
662 this: jobject,
663 field: jfieldID,
664 ) -> Option<Local<'env, R>> {
665 let result = ((**self.env).v1_2.GetObjectField)(self.env, this, field);
666 if result.is_null() {
667 None
668 } else {
669 Some(Local::from_raw(self, result))
670 }
671 }
672
673 pub unsafe fn get_boolean_field(self, this: jobject, field: jfieldID) -> bool {
674 let result = ((**self.env).v1_2.GetBooleanField)(self.env, this, field);
675 result != JNI_FALSE
676 }
677
678 pub unsafe fn get_byte_field(self, this: jobject, field: jfieldID) -> jbyte {
679 ((**self.env).v1_2.GetByteField)(self.env, this, field)
680 }
681
682 pub unsafe fn get_char_field(self, this: jobject, field: jfieldID) -> jchar {
683 ((**self.env).v1_2.GetCharField)(self.env, this, field)
684 }
685
686 pub unsafe fn get_short_field(self, this: jobject, field: jfieldID) -> jshort {
687 ((**self.env).v1_2.GetShortField)(self.env, this, field)
688 }
689
690 pub unsafe fn get_int_field(self, this: jobject, field: jfieldID) -> jint {
691 ((**self.env).v1_2.GetIntField)(self.env, this, field)
692 }
693
694 pub unsafe fn get_long_field(self, this: jobject, field: jfieldID) -> jlong {
695 ((**self.env).v1_2.GetLongField)(self.env, this, field)
696 }
697
698 pub unsafe fn get_float_field(self, this: jobject, field: jfieldID) -> jfloat {
699 ((**self.env).v1_2.GetFloatField)(self.env, this, field)
700 }
701
702 pub unsafe fn get_double_field(self, this: jobject, field: jfieldID) -> jdouble {
703 ((**self.env).v1_2.GetDoubleField)(self.env, this, field)
704 }
705
706 pub unsafe fn set_object_field<R: ReferenceType>(
707 self,
708 this: jobject,
709 field: jfieldID,
710 value: impl AsArg<R>,
711 ) {
712 ((**self.env).v1_2.SetObjectField)(self.env, this, field, value.as_arg());
713 }
714
715 pub unsafe fn set_boolean_field(self, this: jobject, field: jfieldID, value: bool) {
716 ((**self.env).v1_2.SetBooleanField)(
717 self.env,
718 this,
719 field,
720 if value { JNI_TRUE } else { JNI_FALSE },
721 );
722 }
723
724 pub unsafe fn set_byte_field(self, this: jobject, field: jfieldID, value: jbyte) {
725 ((**self.env).v1_2.SetByteField)(self.env, this, field, value);
726 }
727
728 pub unsafe fn set_char_field(self, this: jobject, field: jfieldID, value: jchar) {
729 ((**self.env).v1_2.SetCharField)(self.env, this, field, value);
730 }
731
732 pub unsafe fn set_short_field(self, this: jobject, field: jfieldID, value: jshort) {
733 ((**self.env).v1_2.SetShortField)(self.env, this, field, value);
734 }
735
736 pub unsafe fn set_int_field(self, this: jobject, field: jfieldID, value: jint) {
737 ((**self.env).v1_2.SetIntField)(self.env, this, field, value);
738 }
739
740 pub unsafe fn set_long_field(self, this: jobject, field: jfieldID, value: jlong) {
741 ((**self.env).v1_2.SetLongField)(self.env, this, field, value);
742 }
743
744 pub unsafe fn set_float_field(self, this: jobject, field: jfieldID, value: jfloat) {
745 ((**self.env).v1_2.SetFloatField)(self.env, this, field, value);
746 }
747
748 pub unsafe fn set_double_field(self, this: jobject, field: jfieldID, value: jdouble) {
749 ((**self.env).v1_2.SetDoubleField)(self.env, this, field, value);
750 }
751
752 pub unsafe fn get_static_object_field<R: ReferenceType>(
755 self,
756 class: jclass,
757 field: jfieldID,
758 ) -> Option<Local<'env, R>> {
759 let result = ((**self.env).v1_2.GetStaticObjectField)(self.env, class, field);
760 if result.is_null() {
761 None
762 } else {
763 Some(Local::from_raw(self, result))
764 }
765 }
766
767 pub unsafe fn get_static_boolean_field(self, class: jclass, field: jfieldID) -> bool {
768 let result = ((**self.env).v1_2.GetStaticBooleanField)(self.env, class, field);
769 result != JNI_FALSE
770 }
771
772 pub unsafe fn get_static_byte_field(self, class: jclass, field: jfieldID) -> jbyte {
773 ((**self.env).v1_2.GetStaticByteField)(self.env, class, field)
774 }
775
776 pub unsafe fn get_static_char_field(self, class: jclass, field: jfieldID) -> jchar {
777 ((**self.env).v1_2.GetStaticCharField)(self.env, class, field)
778 }
779
780 pub unsafe fn get_static_short_field(self, class: jclass, field: jfieldID) -> jshort {
781 ((**self.env).v1_2.GetStaticShortField)(self.env, class, field)
782 }
783
784 pub unsafe fn get_static_int_field(self, class: jclass, field: jfieldID) -> jint {
785 ((**self.env).v1_2.GetStaticIntField)(self.env, class, field)
786 }
787
788 pub unsafe fn get_static_long_field(self, class: jclass, field: jfieldID) -> jlong {
789 ((**self.env).v1_2.GetStaticLongField)(self.env, class, field)
790 }
791
792 pub unsafe fn get_static_float_field(self, class: jclass, field: jfieldID) -> jfloat {
793 ((**self.env).v1_2.GetStaticFloatField)(self.env, class, field)
794 }
795
796 pub unsafe fn get_static_double_field(self, class: jclass, field: jfieldID) -> jdouble {
797 ((**self.env).v1_2.GetStaticDoubleField)(self.env, class, field)
798 }
799
800 pub unsafe fn set_static_object_field<R: ReferenceType>(
801 self,
802 class: jclass,
803 field: jfieldID,
804 value: impl AsArg<R>,
805 ) {
806 ((**self.env).v1_2.SetStaticObjectField)(self.env, class, field, value.as_arg());
807 }
808
809 pub unsafe fn set_static_boolean_field(self, class: jclass, field: jfieldID, value: bool) {
810 ((**self.env).v1_2.SetStaticBooleanField)(
811 self.env,
812 class,
813 field,
814 if value { JNI_TRUE } else { JNI_FALSE },
815 );
816 }
817
818 pub unsafe fn set_static_byte_field(self, class: jclass, field: jfieldID, value: jbyte) {
819 ((**self.env).v1_2.SetStaticByteField)(self.env, class, field, value);
820 }
821
822 pub unsafe fn set_static_char_field(self, class: jclass, field: jfieldID, value: jchar) {
823 ((**self.env).v1_2.SetStaticCharField)(self.env, class, field, value);
824 }
825
826 pub unsafe fn set_static_short_field(self, class: jclass, field: jfieldID, value: jshort) {
827 ((**self.env).v1_2.SetStaticShortField)(self.env, class, field, value);
828 }
829
830 pub unsafe fn set_static_int_field(self, class: jclass, field: jfieldID, value: jint) {
831 ((**self.env).v1_2.SetStaticIntField)(self.env, class, field, value);
832 }
833
834 pub unsafe fn set_static_long_field(self, class: jclass, field: jfieldID, value: jlong) {
835 ((**self.env).v1_2.SetStaticLongField)(self.env, class, field, value);
836 }
837
838 pub unsafe fn set_static_float_field(self, class: jclass, field: jfieldID, value: jfloat) {
839 ((**self.env).v1_2.SetStaticFloatField)(self.env, class, field, value);
840 }
841
842 pub unsafe fn set_static_double_field(self, class: jclass, field: jfieldID, value: jdouble) {
843 ((**self.env).v1_2.SetStaticDoubleField)(self.env, class, field, value);
844 }
845
846 pub fn throw<T: ReferenceType>(self, throwable: &Ref<T>) {
847 let res = unsafe { ((**self.env).v1_2.Throw)(self.env, throwable.as_raw()) };
848 assert_eq!(res, 0);
849 }
850}