@@ -26,14 +26,25 @@ use jni::{
2626 errors:: Error ,
2727 objects:: { JMethodID , JObject , JString , JThrowable , JValueOwned } ,
2828 signature:: ReturnType ,
29- Env , JavaVM ,
29+ Env , JavaVM , DEFAULT_LOCAL_FRAME_CAPACITY ,
3030} ;
3131use once_cell:: sync:: OnceCell ;
3232
3333use errors:: { CometError , CometResult } ;
3434
3535pub mod errors;
3636
37+ enum LocalFrameError < E > {
38+ Closure ( E ) ,
39+ Jni ( jni:: errors:: Error ) ,
40+ }
41+
42+ impl < E > From < jni:: errors:: Error > for LocalFrameError < E > {
43+ fn from ( source : jni:: errors:: Error ) -> Self {
44+ Self :: Jni ( source)
45+ }
46+ }
47+
3748/// Global reference to the Java VM, initialized during native library setup.
3849pub static JAVA_VM : OnceCell < JavaVM > = OnceCell :: new ( ) ;
3950
@@ -300,6 +311,13 @@ impl JVMClasses<'_> {
300311 }
301312
302313 /// Runs a closure with an attached JNI environment for the current thread.
314+ ///
315+ /// The closure executes inside a JNI local frame. All JNI local references
316+ /// created inside the closure are freed when the frame is popped on return.
317+ /// Callers must return only Rust values (e.g. `Vec`, `ArrayRef`, scalars);
318+ /// returning a raw JNI local reference will produce a dangling reference
319+ /// after the frame is popped. Panic safety is guaranteed by
320+ /// `jni::Env::with_local_frame`, which pops the frame even on unwinding.
303321 pub fn with_env < T , E , F > ( f : F ) -> Result < T , E >
304322 where
305323 F : FnOnce ( & mut Env ) -> Result < T , E > ,
@@ -316,7 +334,15 @@ impl JVMClasses<'_> {
316334 . attach_current_thread_guard ( Default :: default, & mut scope)
317335 . map_err ( CometError :: from)
318336 . map_err ( E :: from) ?;
319- f ( guard. borrow_env_mut ( ) )
337+ guard
338+ . borrow_env_mut ( )
339+ . with_local_frame ( DEFAULT_LOCAL_FRAME_CAPACITY , |env| {
340+ f ( env) . map_err ( LocalFrameError :: Closure )
341+ } )
342+ . map_err ( |err| match err {
343+ LocalFrameError :: Closure ( err) => err,
344+ LocalFrameError :: Jni ( err) => E :: from ( CometError :: from ( err) ) ,
345+ } )
320346 }
321347 }
322348}
0 commit comments