Skip to content

Commit a1641ab

Browse files
authored
Improve JNI safety (#600)
1 parent 9bbfddf commit a1641ab

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

core/src/jvm_bridge/mod.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
2020
use crate::errors::CometResult;
2121

22+
use jni::objects::JClass;
2223
use jni::{
2324
errors::Error,
2425
objects::{JMethodID, JObject, JString, JThrowable, JValueGen, JValueOwned},
@@ -189,6 +190,12 @@ pub use comet_task_memory_manager::*;
189190

190191
/// The JVM classes that are used in the JNI calls.
191192
pub struct JVMClasses<'a> {
193+
/// Cached JClass for "java.lang.Object"
194+
java_lang_object: JClass<'a>,
195+
/// Cached JClass for "java.lang.Class"
196+
java_lang_class: JClass<'a>,
197+
/// Cached JClass for "java.lang.Throwable"
198+
java_lang_throwable: JClass<'a>,
192199
/// Cached method ID for "java.lang.Object#getClass"
193200
pub object_get_class_method: JMethodID,
194201
/// Cached method ID for "java.lang.Class#getName"
@@ -224,27 +231,32 @@ impl JVMClasses<'_> {
224231
// `JNIEnv` except for creating the global references of the classes.
225232
let env = unsafe { std::mem::transmute::<&mut JNIEnv, &'static mut JNIEnv>(env) };
226233

227-
let clazz = env.find_class("java/lang/Object").unwrap();
234+
let java_lang_object = env.find_class("java/lang/Object").unwrap();
228235
let object_get_class_method = env
229-
.get_method_id(clazz, "getClass", "()Ljava/lang/Class;")
236+
.get_method_id(&java_lang_object, "getClass", "()Ljava/lang/Class;")
230237
.unwrap();
231238

232-
let clazz = env.find_class("java/lang/Class").unwrap();
239+
let java_lang_class = env.find_class("java/lang/Class").unwrap();
233240
let class_get_name_method = env
234-
.get_method_id(clazz, "getName", "()Ljava/lang/String;")
241+
.get_method_id(&java_lang_class, "getName", "()Ljava/lang/String;")
235242
.unwrap();
236243

237-
let clazz = env.find_class("java/lang/Throwable").unwrap();
244+
let java_lang_throwable = env.find_class("java/lang/Throwable").unwrap();
238245
let throwable_get_message_method = env
239-
.get_method_id(clazz, "getMessage", "()Ljava/lang/String;")
246+
.get_method_id(&java_lang_throwable, "getMessage", "()Ljava/lang/String;")
240247
.unwrap();
241248

242-
let clazz = env.find_class("java/lang/Throwable").unwrap();
243249
let throwable_get_cause_method = env
244-
.get_method_id(clazz, "getCause", "()Ljava/lang/Throwable;")
250+
.get_method_id(&java_lang_throwable, "getCause", "()Ljava/lang/Throwable;")
245251
.unwrap();
246252

253+
// SAFETY: According to the documentation for `JMethodID`, it is our
254+
// responsibility to maintain a reference to the `JClass` instances where the
255+
// methods were accessed from to prevent the methods from being garbage-collected
247256
JVMClasses {
257+
java_lang_object,
258+
java_lang_class,
259+
java_lang_throwable,
248260
object_get_class_method,
249261
class_get_name_method,
250262
throwable_get_message_method,

0 commit comments

Comments
 (0)