Skip to content

Commit 36e8a24

Browse files
committed
Fix: Android doesn't support JNI_GetCreatedVMs
1 parent 051262c commit 36e8a24

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

src/easytier/linkage_impl.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use std::fmt::Write;
99
use std::net::Ipv4Addr;
1010
use std::sync::{Arc, RwLock};
1111
use std::time::Duration;
12-
use easytier::proto::common::Ipv4Inet;
1312
use tokio::runtime::Handle;
1413
use toml::{Table, Value};
1514

src/lib.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
string_from_utf8_lossy_owned
99
)]
1010

11-
extern crate core;#[cfg(not(target_os = "android"))]
11+
extern crate core;
12+
#[cfg(not(target_os = "android"))]
1213
compile_error!("Terracotta lib mode is intended for Android platform.");
1314

1415
#[macro_export]
@@ -22,10 +23,9 @@ use lazy_static::lazy_static;
2223

2324
use chrono::{FixedOffset, TimeZone, Utc};
2425
use jni::signature::{Primitive, ReturnType};
25-
use jni::sys::{jbyte, jshort, jvalue, JNI_GetCreatedJavaVMs, JNI_OK};
26+
use jni::sys::{jshort, jsize, jvalue, JavaVM};
2627
use jni::{objects::JString, strings::JavaStr, sys::{jboolean, jint, jobject, JNI_FALSE, JNI_TRUE}, JNIEnv};
2728
use libc::{c_char, c_int};
28-
use std::sync::{LazyLock, OnceLock};
2929
use std::time::Duration;
3030
use std::{
3131
env, ffi::CString, fs, net::{IpAddr, Ipv4Addr, Ipv6Addr}, ptr::null_mut, sync::{Arc, Mutex}, thread,
@@ -96,7 +96,13 @@ static VPN_SERVICE_CFG: Mutex<Option<crate::easytier::EasyTierTunRequest>> = Mut
9696

9797
#[unsafe(no_mangle)]
9898
#[allow(non_snake_case)]
99-
extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0(_env: JNIRawEnv) -> jint {
99+
extern "system" fn JNI_GetCreatedJavaVMs(vmBuf: *mut *mut JavaVM, bufLen: jsize, nVMs: *mut jsize) -> jint {
100+
unreachable!();
101+
}
102+
103+
#[unsafe(no_mangle)]
104+
#[allow(non_snake_case)]
105+
extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0(env: JNIRawEnv) -> jint {
100106
cfg_if::cfg_if! {
101107
if #[cfg(debug_assertions)] {
102108
std::panic::set_backtrace_style(std::panic::BacktraceStyle::Short);
@@ -140,19 +146,15 @@ extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0(_e
140146
return 2;
141147
}
142148

143-
thread::spawn(|| {
144-
let jvm = unsafe {
145-
let mut vm: *mut jni::sys::JavaVM = null_mut();
146-
let mut count: i32 = 0;
147-
if JNI_GetCreatedJavaVMs(&mut vm, 1, &mut count) == JNI_OK && count > 0 {
148-
jni::JavaVM::from_raw(vm).unwrap()
149-
} else {
150-
panic!("Cannot locate created VMs.");
151-
}
152-
};
149+
let mut jenv = unsafe { JNIEnv::from_raw(env) }.unwrap();
150+
let jvm = jenv.get_java_vm().unwrap();
153151

152+
// In Native daemon thread, it's impossible to access TerracottaAndroidAPI with find_class.
153+
// So we find them here and use a global ref to hold it.
154+
let callback_class = jenv.find_class("net/burningtnt/terracotta/TerracottaAndroidAPI").unwrap();
155+
let callback_class = jenv.new_global_ref(callback_class).unwrap();
156+
thread::spawn(move || {
154157
let mut jenv = jvm.attach_current_thread_as_daemon().unwrap();
155-
let callback_class = jenv.find_class("net/burningtnt/terracotta/TerracottaAndroidAPI").unwrap();
156158
let callback_method = jenv.get_static_method_id(
157159
&callback_class, "onVpnServiceStateChanged", "(BBBBSLjava/lang/String;)I"
158160
).unwrap();

0 commit comments

Comments
 (0)