Multi-threaded c/c ++ code in cocos2d-x calls java code through JNI

Source: Internet
Author: User

 

This is the second article about android multithread in c/c ++ to call JNI.

First Article address: http://blog.csdn.net/wu4long/article/details/17756419

As mentioned above, the third method of android isClassLoaderObject.

 

  • Cache a reference toClassLoaderObject somewhere handy, and issueloadClassCILS directly. This requires some effort.

     

    What should I do? (This requires some effort )?

    Below I will be specific to the cocos2d-x environment to describe. Of course, you can modify the environment by yourself.

    This article is based on the http://stackoverflow.com/questions/13263340/findclass-from-any-thread-in-android-jni

    FindClass from any thread in Android JNI but this article is not written for cocos2d-x. In some cases, the Code is not rigorous.

     

     

    /// Return true if success. else return false.

    Bool your_thread_start_javaVMAttachCurrentThread ()

     

    {

     

    JNIEnv * env = NULL;

    If (JniHelper: getJavaVM ()-> AttachCurrentThread (& env, NULL) <0) return false;

    Return true;

    }

    Void your_thread_stop_javaVMDetachCurrentThread ()

    {

    JniHelper: getJavaVM ()-> DetachCurrentThread ();

    }

    Start calling your_thread_start_javaVMAttachCurrentThread () in the thread function, and call your_thread_stop_javaVMDetachCurrentThread () at the end of the thread (). Handle the error.

    The two functions above can be placed in what you think is appropriate. Of course, it can also be placed directly in the JniHelper class. Handle it by yourself.

     

     

    In order to continue using JniHelper, the problem of Multithreading can be avoided transparently. We can directly modify the JniHelper. cpp file.

     

     

    Static jobject gClassLoader;

    Static jmethodID gFindClassMethod;


    Add a new function:

    Static void initClassLoaderForMultiThread ()

    {

     

    JNIEnv * env = 0;

    Do

    {

    If (! GetEnv (& env ))

    {

    Break;

    }

    Jclass cocos2dClass = env-> FindClass (Org/Cocos2dx/Lib/Cocos2dxRenderer );

    If (env-> ExceptionCheck ())

    {

    Env-> predictiondescribe ();

    Env-> ExceptionClear ();

    LOGD (ExceptioninitClassLoaderForMultiThread cocos2dClass is exception );

    Break;

    }

     

    /// Env-> FindClass (java/lang/Class );

    Jclass classClass = env-> GetObjectClass (cocos2dClass );

    If (env-> ExceptionCheck ())

    {

    Env-> predictiondescribe ();

    Env-> ExceptionClear ();

    LOGD (Exception initClassLoaderForMultiThread classClass is exception );

    Break;

    }

     

     

    Jclass classLoaderClass = env-> FindClass (java/Lang/ClassLoader );

    If (env-> ExceptionCheck ())

    {

    Env-> predictiondescribe ();

    Env-> ExceptionClear ();

    LOGD (Exception initClassLoaderForMultiThread classLoaderClass );

    Break;

    }

     

    JmethodID getClassLoaderMethod = env-> GetMethodID (classClass, getClassLoader,

    ()Ljava/Lang/ClassLoader ;);

     

    Jobject classLoader = env-> CallObjectMethod (cocos2dClass, getClassLoaderMethod );

     

    If (env-> ExceptionCheck ())

    {

    Env-> predictiondescribe ();

    Env-> ExceptionClear ();

    LOGD (Exception initClassLoaderForMultiThread classLoader );

    Break;

    }

     

    GClassLoader = env-> NewGlobalRef (classLoader );

     

    JmethodID findClassMethod = env-> GetMethodID (classLoaderClass, findClass ,(Ljava/Lang/String ;)Ljava/Lang/Class ;);

     

     

    GFindClassMethod = findClassMethod;

     

    If (env-> ExceptionCheck ())

    {

    Env-> predictiondescribe ();

    Env-> ExceptionClear ();

    GFindClassMethod = NULL;

    GClassLoader = NULL;

    LOGD (Exception initClassLoaderForMultiThread findClassMethod );

    Break;

    }

    } While (0 );

    }

    Then, call the above function in the JniHelper: setJavaVM function. As follows:

     

    Void JniHelper: setJavaVM (JavaVM * javaVM)

    {

    M_psJavaVM = javaVM;

    InitClassLoaderForMultiThread ();}

     

    Then modify the getClassID _ function. Add the gray shadow section below. That is, when the original FindClass fails,

    Use our new ClassLoader method to find classes.

    Ret = static_cast (PEnv-> CallObjectMethod (gClassLoader, gFindClassMethod, jstrName ));

     

     

    Static jclass getClassID _ (constchar * className, JNIEnv * env)

    {

    JNIEnv * pEnv = env;

    Jclass ret = 0;

     

    Do

    {

    If (! PEnv)

    {

    If (! GetEnv (& pEnv ))

    {

    Break;

    }

    }

     

    Ret = pEnv-> FindClass (className );

     

    If (! Ret)

    {

    If (gClassLoader)

    {

    If (pEnv-> predictioncheck ())

    {

    PEnv-> predictiondescribe ();

    PEnv-> predictionclear ();

    }

    Jstring jstrName = (pEnv)-> NewStringUTF (className );

    Ret = static_cast (PEnv-> CallObjectMethod (gClassLoader, gFindClassMethod, jstrName ));

    If (ret) break;

    }

    LOGD (Failed to find class of % s, className );

    Break;

    }

    } While (0 );

     

    Return ret;

    }


    Then, in your thread code, you can use JniHelper to call the corresponding method.

     

    JniHelper: getStaticMethodInfo and other methods are the same as those of a single thread.

     

    It's done. Multi-threading can be processed transparently.

    If your environment is not cocos2dx, you only need to modify and move the added part to your environment.

    The only difference is that

    Jclass cocos2dClass = env-> FindClass (Org/Cocos2dx/Lib/Cocos2dxRenderer );

    You can replace the org/cocos2dx/lib/Cocos2dxRenderer string with the java class that must exist in your environment.

     

    Resource synchronization of the supplemental thread:

    If java-side resource synchronization is required between threads. You can use jint MonitorEnter (jobject obj); and jint MonitorExit (jobject obj );

    Similar to a simple synchronization lock, we write this in Java

     

    Synchronized (obj ){
    // Dosomething
    }

    In JNI, we use this set of functions. Of course, we first get this object through the Jni method.

    Jobject obj = ....;

    Env-> MonitorEnter (obj );

    // Dosomething
    Env-> MonitorExit (obj );


     


     

     

     

     

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.