[Solved] How to pass by reference a QAndroidJniEnvironment object to a Qthread?



  • I have a thread object that works In the qt main thread I successfully can run this:

    jbyteArray jBuffer = _env->NewByteArray(bufferSize);
    

    The _env is a QAndroidJniEnvironment. but If I try to use _env in the run function of a Runnable, the application crashes and this error occurs:

    Fatal signal 11 (SIGSEGV), code 1
    

    This is the code:

    class HelloWorldTask : public QRunnable
    {
    QAndroidJniEnvironment * _env;
    void run()
    {
        qDebug() << "Hello world from thread" << QThread::currentThread();
        jbyteArray jBuffer = (*_env)->NewByteArray(10);
        qDebug() << "Hello 2 world from thread" << QThread::currentThread();
    }
    public:
    void setPointer(QAndroidJniEnvironment * p){
        _env = p;
    }
    };
    
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    HelloWorldTask * hello = new HelloWorldTask();
    QAndroidJniEnvironment env;
    QAndroidJniEnvironment * p = & env;
    hello->setPointer(p);
    QThreadPool::globalInstance()->start(hello);
    return a.exec();
    }
    

    Could you please tell me how can I use the pointer to the QAndroidJniEnvironment or QAndroidJniObject in a new Qthread? so the application ui remains responsive during the execution of java process.



  • To use an jni environment pointer by a different thread you have to call AttachCurrentThread.



  • @sneubert
    Thanks for your reply. I tried he following code but I got fatal signal again!

    JavaVM * _jvm = 0;
    JNIEnv* _jniENV;
    qDebug() << "Attaching current thread";
    _jvm->AttachCurrentThread(&_jniENV,NULL);
    

    Here is full error description:

    D/Qt      (14352): ..\untitled4\main.cpp:47 (int main(int, char**)): Attaching current thread
    F/libc    (14352): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 14508 (QtThread)


  • @a.toraby
    _jvm and _jniENV are initialised ?



  • _jniENV is a pointer already so try to pass it without & to AttachCurrentThread



  • @a.toraby said:

    JavaVM * _jvm = 0;
    JNIEnv* _jniENV;
    qDebug() << "Attaching current thread";
    _jvm->AttachCurrentThread(&_jniENV,NULL);

    As i see here _jvm - is a null pointer.. and you call method from null pointer



  • @jalomic said:

    @a.toraby said:

    JavaVM * _jvm = 0;
    JNIEnv* _jniENV;
    qDebug() << "Attaching current thread";
    _jvm->AttachCurrentThread(&_jniENV,NULL);

    As i see here _jvm - is a null pointer.. and you call method from null pointer

    Yes you are right. I solved it by using a QAndroidJniEnvironment: Here is the working code:

    class HelloWorldTask : public QRunnable
    {
    QAndroidJniEnvironment * _env;
    void run()
    {
        JNIEnv * jniEnv;
        JavaVM * jvm = _env->javaVM();
        qDebug() << "Getting jni environment";
        jvm->GetEnv(reinterpret_cast<void**>(&_env), JNI_VERSION_1_6);
        qDebug() << "Attaching current thread";
        jvm->AttachCurrentThread(&jniEnv,NULL);
        qDebug() << "Creating byte array" ;
        jbyteArray jBuffer = jniEnv->NewByteArray(10);
        qDebug() << "byte array created" ;
        jvm->DetachCurrentThread();
    }
    public:
    void setPointer(QAndroidJniEnvironment * p){
        _env = p;
    }
    };
    
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    
    
    HelloWorldTask * hello = new HelloWorldTask();
    
    
    QAndroidJniEnvironment * env;
    hello->setPointer(env);
    // QThreadPool takes ownership and deletes 'hello' automatically
    QThreadPool::globalInstance()->start(hello);
    return a.exec();
    }

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.