ShadowySpirits commented on code in PR #2112:
URL:
https://github.com/apache/incubator-opendal/pull/2112#discussion_r1177546688
##########
bindings/java/src/lib.rs:
##########
@@ -15,20 +15,97 @@
// specific language governing permissions and limitations
// under the License.
+use std::cell::RefCell;
use std::collections::HashMap;
+use std::ffi::c_void;
use std::str::FromStr;
+use std::sync::Arc;
-use jni::objects::JClass;
use jni::objects::JMap;
use jni::objects::JObject;
use jni::objects::JString;
-use jni::sys::jboolean;
-use jni::sys::jlong;
-use jni::JNIEnv;
+use jni::objects::{JClass, JValue};
+use jni::sys::{jboolean, jint};
+use jni::sys::{jlong, JNI_VERSION_1_8};
+use jni::{JNIEnv, JavaVM};
+use once_cell::sync::OnceCell;
+use tokio::runtime::{Builder, Runtime};
+
use opendal::BlockingOperator;
use opendal::Operator;
use opendal::Scheme;
+static mut RUNTIME: OnceCell<Runtime> = OnceCell::new();
+
+thread_local! {
+ static JAVA_VM: RefCell<Option<Arc<JavaVM>>> = RefCell::new(None);
+ static JENV: RefCell<Option<*mut jni::sys::JNIEnv>> = RefCell::new(None);
+}
+
+fn get_system_property(env: &mut JNIEnv, key: &str) -> Result<String,
jni::errors::Error> {
+ let system_class = env.find_class("java/lang/System")?;
+ let key = env.new_string(key)?;
+ let value = env.call_static_method(
+ system_class,
+ "getProperty",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ &[JValue::Object(key.as_ref())],
+ )?;
+
+ Ok(env
+ .get_string(JString::from(value.l().unwrap()).as_ref())?
+ .into())
+}
+
+/// # Safety
+///
+/// This function could be only called by java vm when load this lib.
+#[no_mangle]
+pub unsafe extern "system" fn JNI_OnLoad(vm: JavaVM, _: *mut c_void) -> jint {
+ let mut env = vm.get_env().unwrap();
+ let thread_count = match get_system_property(&mut env,
"opendal.thread.count") {
+ Ok(count) => count.parse().unwrap_or(num_cpus::get()),
+ Err(_) => num_cpus::get(),
+ };
+
+ let java_vm = Arc::new(vm);
+ let runtime = Builder::new_multi_thread()
+ .worker_threads(thread_count)
+ .on_thread_start(move || {
+ JENV.with(|cell| {
+ let env = java_vm.attach_current_thread_as_daemon().unwrap();
+ *cell.borrow_mut() = Some(env.get_raw());
+ });
+ JAVA_VM.with(|cell| {
+ *cell.borrow_mut() = Some(java_vm.clone());
+ });
+ })
+ .on_thread_stop(move || {
+ JENV.with(|cell| {
+ *cell.borrow_mut() = None;
+ });
+ JAVA_VM.with(|cell| unsafe {
+ if let Some(vm) = cell.borrow_mut().take() {
+ vm.detach_current_thread();
+ }
+ });
+ })
+ .build()
+ .unwrap();
+ RUNTIME.set(runtime).unwrap();
+ JNI_VERSION_1_8
Review Comment:
> JNI_OnLoad must return the JNI version needed by the native library
Reference:
https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#JNJI_OnLoad
It is better to select a minimum version that fulfills our requirements,
similar to MSRV.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]