This is an automated email from the ASF dual-hosted git repository. xuanwo pushed a commit to branch xuanwo/lyon-v1 in repository https://gitbox.apache.org/repos/asf/opendal.git
commit b058bcd57c5a93e06ffb5e3431bddae04c02498b Author: Xuanwo <[email protected]> AuthorDate: Sat Dec 13 00:20:02 2025 +0800 fix(bindings/java): Detach current thread while thread drop Signed-off-by: Xuanwo <[email protected]> --- bindings/java/src/executor.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/bindings/java/src/executor.rs b/bindings/java/src/executor.rs index 0db816884..e1b9c4dc2 100644 --- a/bindings/java/src/executor.rs +++ b/bindings/java/src/executor.rs @@ -19,8 +19,8 @@ use std::cell::RefCell; use std::ffi::c_void; use std::future::Future; use std::num::NonZeroUsize; -use std::sync::OnceLock; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, OnceLock}; use std::thread::available_parallelism; use jni::JNIEnv; @@ -116,7 +116,8 @@ pub unsafe extern "system" fn Java_org_apache_opendal_AsyncExecutor_disposeInter } pub(crate) fn make_tokio_executor(env: &mut JNIEnv, cores: usize) -> Result<Executor> { - let vm = env.get_java_vm().expect("JavaVM must be available"); + let vm = Arc::new(env.get_java_vm().expect("JavaVM must be available")); + let stop_vm = vm.clone(); let counter = AtomicUsize::new(0); let executor = tokio::runtime::Builder::new_multi_thread() .worker_threads(cores) @@ -135,6 +136,18 @@ pub(crate) fn make_tokio_executor(env: &mut JNIEnv, cores: usize) -> Result<Exec *cell.borrow_mut() = Some(env.get_raw()); }) }) + .on_thread_stop(move || { + ENV.with(|cell| { + *cell.borrow_mut() = None; + }); + + // `jni` will normally detach daemon threads via a TLS destructor, which can lead to + // deadlocks on Windows during DLL unload. Detach explicitly while the thread is + // still running to clear the TLS guard. + unsafe { + stop_vm.detach_current_thread(); + } + }) .enable_all() .build() .map_err(|e| {
