Могу ли я использовать std::unique_lock для присоединения currentThread и отсоединения currentThread от JNI?

#android #c

#Android #c

Вопрос:

     class SmartAttachCurrentThread
    {
    public:
        SmartAttachCurrentThread(JavaVM *jvm, JNIEnv *env) : jvm(jvm), env(env)
        {
            //TODO: throw if jvm null?
            jvm->AttachCurrentThread(amp;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:

Ваш конструктор класса принимает JNIEnv* параметр по значению, поэтому env переменная вне класса не обновляется. Вместо этого вам нужно передать его по ссылке, например:

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

        if (jvm->AttachCurrentThread(amp;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, amp;env);
    // now you can use env as needed...
}