|
19 | 19 |
|
20 | 20 | use crate::errors::CometResult; |
21 | 21 |
|
| 22 | +use jni::objects::JClass; |
22 | 23 | use jni::{ |
23 | 24 | errors::Error, |
24 | 25 | objects::{JMethodID, JObject, JString, JThrowable, JValueGen, JValueOwned}, |
@@ -189,6 +190,12 @@ pub use comet_task_memory_manager::*; |
189 | 190 |
|
190 | 191 | /// The JVM classes that are used in the JNI calls. |
191 | 192 | 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>, |
192 | 199 | /// Cached method ID for "java.lang.Object#getClass" |
193 | 200 | pub object_get_class_method: JMethodID, |
194 | 201 | /// Cached method ID for "java.lang.Class#getName" |
@@ -224,27 +231,32 @@ impl JVMClasses<'_> { |
224 | 231 | // `JNIEnv` except for creating the global references of the classes. |
225 | 232 | let env = unsafe { std::mem::transmute::<&mut JNIEnv, &'static mut JNIEnv>(env) }; |
226 | 233 |
|
227 | | - let clazz = env.find_class("java/lang/Object").unwrap(); |
| 234 | + let java_lang_object = env.find_class("java/lang/Object").unwrap(); |
228 | 235 | 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;") |
230 | 237 | .unwrap(); |
231 | 238 |
|
232 | | - let clazz = env.find_class("java/lang/Class").unwrap(); |
| 239 | + let java_lang_class = env.find_class("java/lang/Class").unwrap(); |
233 | 240 | 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;") |
235 | 242 | .unwrap(); |
236 | 243 |
|
237 | | - let clazz = env.find_class("java/lang/Throwable").unwrap(); |
| 244 | + let java_lang_throwable = env.find_class("java/lang/Throwable").unwrap(); |
238 | 245 | 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;") |
240 | 247 | .unwrap(); |
241 | 248 |
|
242 | | - let clazz = env.find_class("java/lang/Throwable").unwrap(); |
243 | 249 | 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;") |
245 | 251 | .unwrap(); |
246 | 252 |
|
| 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 |
247 | 256 | JVMClasses { |
| 257 | + java_lang_object, |
| 258 | + java_lang_class, |
| 259 | + java_lang_throwable, |
248 | 260 | object_get_class_method, |
249 | 261 | class_get_name_method, |
250 | 262 | throwable_get_message_method, |
|
0 commit comments