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::ops::Deref;
16use std::sync::OnceLock;
17
18use anyhow::Context as _;
19use jni::JavaVM;
20
21/// Type alias for a function that builds a JVM.
22pub type JvmBuilder = fn() -> anyhow::Result<JavaVM>;
23
24/// Registered JVM builder from other crates. Should only be one.
25#[linkme::distributed_slice]
26pub static JVM_BUILDER: [JvmBuilder];
27
28/// Wrapper for the global JVM instance.
29///
30/// To obtain the instance, use [`Jvm::get_or_init()`] or [`Jvm::get()`].
31#[derive(Clone, Copy, Debug)]
32#[repr(transparent)]
33pub struct Jvm(pub &'static JavaVM);
34
35static INSTANCE: OnceLock<JavaVM> = OnceLock::new();
36
37impl Jvm {
38    /// Get the global singleton JVM instance, initializing it with the registered builder if not already initialized.
39    pub fn get_or_init() -> anyhow::Result<Self> {
40        INSTANCE
41            .get_or_try_init(|| {
42                let builder = JVM_BUILDER
43                    .iter()
44                    .next()
45                    .context("no JVM builder is registered")?;
46                builder()
47            })
48            .map(Self)
49    }
50
51    /// Get the global singleton JVM instance, returning `None` if not initialized.
52    ///
53    /// Use [`Jvm::get_or_init()`] if you want to initialize the JVM.
54    pub fn get() -> Option<Self> {
55        INSTANCE.get().map(Self)
56    }
57}
58
59impl Deref for Jvm {
60    type Target = JavaVM;
61
62    fn deref(&self) -> &Self::Target {
63        self.0
64    }
65}