From 7763deb15480cbc3f4484e69fea547d164ebdaf3 Mon Sep 17 00:00:00 2001 From: Falk Woldmann Lu <52786457+FalkWoldmann@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:40:47 +0200 Subject: [PATCH] Replace once_cell with std::sync::OnceLock OnceLock::get_or_try_init isn't stable yet, so values are built before being stored. --- Cargo.lock | 1 - rustls-platform-verifier/Cargo.toml | 4 +- rustls-platform-verifier/src/android.rs | 57 ++++++++++++++----------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4fb4edc..fa158d14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1191,7 +1191,6 @@ dependencies = [ "core-foundation-sys", "jni", "log", - "once_cell", "rustls", "rustls-native-certs", "rustls-platform-verifier-android 0.2.0", diff --git a/rustls-platform-verifier/Cargo.toml b/rustls-platform-verifier/Cargo.toml index cf714348..f2cfce5a 100644 --- a/rustls-platform-verifier/Cargo.toml +++ b/rustls-platform-verifier/Cargo.toml @@ -22,21 +22,19 @@ dbg = [] # by the platform's verifier. cert-logging = ["base64"] # Used for nicely documenting the Android-specific APIs. This feature is not stable. -docsrs = ["jni", "once_cell"] +docsrs = ["jni"] [dependencies] rustls = { version = "0.23.27", default-features = false, features = ["std"] } log = { version = "0.4" } base64 = { version = "0.22", optional = true } # Only used when the `cert-logging` feature is enabled. jni = { version = "0.22.4", default-features = false, optional = true } # Only used during doc generation -once_cell = { version = "1.9", optional = true } # Only used during doc generation [target.'cfg(all(unix, not(target_os = "android"), not(target_vendor = "apple"), not(target_arch = "wasm32")))'.dependencies] rustls-native-certs = "0.8" webpki = { package = "rustls-webpki", version = "0.103", default-features = false } [target.'cfg(target_os = "android")'.dependencies] -once_cell = "1.9" rustls-platform-verifier-android = { path = "../android-release-support", version = "0.2.0" } jni = { version = "0.22", default-features = false } webpki = { package = "rustls-webpki", version = "0.103", default-features = false } diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index 1e36bedf..9af5c794 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -23,9 +23,9 @@ use jni::errors::Error as JNIError; use jni::objects::{Global, JClass, JClassLoader, JObject}; use jni::strings::JNIStr; use jni::{jni_sig, jni_str, Env, JavaVM}; -use once_cell::sync::OnceCell; +use std::sync::OnceLock; -static GLOBAL: OnceCell = OnceCell::new(); +static GLOBAL: OnceLock = OnceLock::new(); /// A layer to access the Android runtime which is hosting the current /// application process. @@ -95,23 +95,25 @@ fn global() -> &'static GlobalStorage { /// This method will setup and store an environment locally. This is useful if nothing else in your /// application needs to access the Android runtime. pub fn init_with_env(env: &mut Env, context: JObject) -> Result<(), JNIError> { - GLOBAL.get_or_try_init(|| -> Result<_, JNIError> { - let loader = env - .call_method( - &context, - jni_str!("getClassLoader"), - jni_sig!(() -> JClassLoader), - &[], - )? - .l()?; - let loader = env.cast_local::(loader)?; - - Ok(GlobalStorage::Internal { - java_vm: env.get_java_vm()?, - context: env.new_global_ref(context)?, - loader: env.new_global_ref(loader)?, - }) - })?; + if GLOBAL.get().is_some() { + return Ok(()); + } + + let loader = env + .call_method( + &context, + jni_str!("getClassLoader"), + jni_sig!(() -> JClassLoader), + &[], + )? + .l()?; + let loader = env.cast_local::(loader)?; + + let _ = GLOBAL.set(GlobalStorage::Internal { + java_vm: env.get_java_vm()?, + context: env.new_global_ref(context)?, + loader: env.new_global_ref(loader)?, + }); Ok(()) } @@ -225,7 +227,7 @@ where /// Loads and caches a class on first use pub(super) struct CachedClass { name: &'static JNIStr, - class: OnceCell>>, + class: OnceLock>>, } impl CachedClass { @@ -233,17 +235,20 @@ impl CachedClass { pub(super) const fn new(name: &'static JNIStr) -> Self { Self { name, - class: OnceCell::new(), + class: OnceLock::new(), } } /// Gets the cached class reference, loaded on first use pub(super) fn get(&self, cx: &mut LocalContext) -> Result<&JClass<'static>, Error> { - let class = self.class.get_or_try_init(|| -> Result<_, Error> { - let class = cx.load_class(self.name)?; - - Ok(cx.env.new_global_ref(class)?) - })?; + let class = self.class.get().map_or_else( + || -> Result<_, Error> { + let class = cx.load_class(self.name)?; + let class = cx.env.new_global_ref(class)?; + Ok(self.class.get_or_init(|| class)) + }, + Ok, + )?; Ok(class) }