我可以使用std :: unique_lock来连接JNI的AttachCurrentThread和DetachCurrentThread吗?

时间:2020-09-22 09:27:53

标签: android c++

    class SmartAttachCurrentThread
    {
    public:
        SmartAttachCurrentThread(JavaVM *jvm, JNIEnv *env) : jvm(jvm), env(env)
        {
            //TODO: throw if jvm null?
            jvm->AttachCurrentThread(&env, NULL);
        }

        ~SmartAttachCurrentThread()
        {
            jvm->DetachCurrentThread();
        }

    private:
        JNIEnv *env;
        JavaVM *jvm;
    };

我正在尝试设计一个智能类,该类为我附加当前的jni线程并自动分离,因此可以这样使用:

    {
        JNIEnv *env;
        SmartAttachCurrentThread smartAttachCurrentThread(jvm, env);
        jclass clazz;
        clazz = env->FindClass("com/app/myapp/");
        //call class method
        //thread is detached here prevnting memory leak 
    }

但是,AttachCurrentThread中的SmartAttachCurrentThread不会更改行上的JNIEnv *env;

 {
        JNIEnv *env;

对此有什么好的解决方案?我真的需要这个类吗?或者我可以对某些std::unique_lock<T>类型使用T吗?

1 个答案:

答案 0 :(得分:1)

您的类构造函数正在按值使用JNIEnv*参数 ,这就是为什么不更新类外部的env变量的原因。您需要改为通过引用传递 ,例如:

class SmartAttachCurrentThread
{
public:
    SmartAttachCurrentThread(JavaVM *jvm, JNIEnv* &env) : jvm(jvm)
    {
        if (!jvm)
            throw ...; // whatever you want

        if (jvm->AttachCurrentThread(&env, NULL) != JNI_OK)
            throw ...; // whatever you want
    }

    ~SmartAttachCurrentThread()
    {
        jvm->DetachCurrentThread();
    }

private:
    JavaVM *jvm;
};

...

{
    JNIEnv *env;
    SmartAttachCurrentThread smartAttachCurrentThread(jvm, env);
    // now you can use env as needed...
}

或者,通过指针传递它,例如:

class SmartAttachCurrentThread
{
public:
    SmartAttachCurrentThread(JavaVM *jvm, JNIEnv **env) : jvm(jvm)
    {
        if (!jvm || !env)
            throw ...; // whatever you want

        if (jvm->AttachCurrentThread(env, NULL) != JNI_OK)
            throw ...; // whatever you want
    }

    ~SmartAttachCurrentThread()
    {
        jvm->DetachCurrentThread();
    }

private:
    JavaVM *jvm;
};

...

{
    JNIEnv *env;
    SmartAttachCurrentThread smartAttachCurrentThread(jvm, &env);
    // now you can use env as needed...
}