risingwave_common/
global_jvm.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::{Mutex, OnceLock};
16
17use jni::JavaVM;
18
19pub static JVM: JavaVmWrapper = JavaVmWrapper;
20static INSTANCE: OnceLock<JavaVM> = OnceLock::new();
21static JVM_BUILDER: Mutex<Option<Box<dyn Fn() -> JavaVM + Send + Sync>>> = Mutex::new(None);
22
23pub struct JavaVmWrapper;
24
25impl JavaVmWrapper {
26    pub fn register_jvm_builder(&self, builder: Box<dyn Fn() -> JavaVM + Send + Sync>) {
27        let mut guard = JVM_BUILDER.lock().unwrap();
28        if guard.is_some() {
29            tracing::warn!("JVM builder already registered, overwriting the previous one.");
30        }
31        *guard = Some(builder);
32    }
33
34    /// Get the global singleton JVM instance, initializing it with the registered closure if not already initialized.
35    pub fn get_or_init(&self) -> anyhow::Result<&'static JavaVM> {
36        INSTANCE.get_or_try_init(|| {
37            let guard = JVM_BUILDER.lock().unwrap();
38            let builder = guard.as_ref().ok_or_else(|| {
39                anyhow::anyhow!("JVM builder must be registered (and only once) before get_or_init")
40            })?;
41            Ok(builder())
42        })
43    }
44
45    /// Get the global singleton JVM instance, returning None if not initialized.
46    pub fn get(&self) -> Option<&'static JavaVM> {
47        INSTANCE.get()
48    }
49}