在JNI中避免使用全局静态变量

Java 可以加载一个类的多个实例(因为例如有多个类加载器classloader),并且静态变量将在所有实例之间共享。 不幸的是,清理调用也是如此,如果您的类的一个实例被销毁而另一个仍在使用中,则会导致不一致。

在这些情形,使用 native class constructor / finalizer 并分配/取消 内存资源 会更明智。

你不能假设 Java会以单线程模式调用natvie函数。


大多数代码只需要在一个线程里运行,这样,就不需要锁定机制。
但是,不能因为只有一个线程, 就直接用 static mut, 并将 对它的访问 wrap到unsafe代码块里。
这样可能会出现严重的内存问题。
举个例子, 从全局变量中不安全地借用可能会同时给我们多个可变引用。 然后我们可以使用其中一个来迭代一个向量,
但另一个却从同一个向量中删除值。 然后迭代器可能会超出有效的内存边界,这种潜在崩溃, 是安全的 Rust 可以防止的。

Rust标准库, 提供了一种“全局”存储值的方法,可在单个线程中安全访问。这就是 thread local.
在多线程的情况下,每个线程都会获得变量的独立副本。

thread local优缺点

坏处就是, 该静态对象,对你的程序产生的其他线程,并不可见。
好处就是,与真正的全局状态不同,它是完全安全的,无痛使用— 真正的全局状态,在任何语言中,都是一个巨大的痛苦。

使用thread local不是最简单的方案,但是它允许执行任意的初始化代码, 这些初始化代码
只有在第1次 访问该变量的值时,才会执行。


use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref PRIVILEGES: HashMap<&'static str, Vec<&'static str>> = {
        let mut map = HashMap::new();
        map.insert("James", vec!["user", "admin"]);
        map.insert("Jim", vec!["user"]);
        map
    };
}

fn show_access(name: &str) {
    let access = PRIVILEGES.get(name);
    println!("{}: {:?}", name, access);
}

fn main() {
    let access = PRIVILEGES.get("James");
    println!("James: {:?}", access);

    show_access("Jim");
}

lazy_static! {
    static ref USER_TOKEN_HASHMAP: Mutex> = Mutex::new(HashMap::new());
}

fn func() {
    let mut _map = USER_TOKEN_HASHMAP.lock().unwrap();
    let user_email = String::from("aaa");
    let user_password = String::from("bbb");
    _map.insert(user_email, user_password);
}

必须用Mutex

参考资料
https://www.sitepoint.com/rust-global-variables/

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注