精华内容
下载资源
问答
  • 我能够运行类似的代码(如下所示),其中有线程访问同一JVM(macOS).我正在使用pthread.很少有重要的事情>将线程附加到JVM(根据文档,一次只能有一个线程可以使用JVM)>连接螺纹>我想也最好使用互斥体以防止...

    我能够运行类似的代码(如下所示),其中有多个线程访问同一JVM(macOS).我正在使用pthread.

    很少有重要的事情

    >将线程附加到JVM(根据文档,一次只能有一个线程可以使用JVM)

    >连接螺纹

    >我想也最好使用互斥体以防止连接多个线程

    main.c

    #include

    #include

    #include

    #define NUM_THREADS 6

    pthread_mutex_t mutexjvm;

    pthread_t threads[NUM_THREADS];

    struct JVM {

    JNIEnv *env;

    JavaVM *jvm;

    };

    void invoke_class(JNIEnv* env);

    void *jvmThreads(void* myJvm) {

    struct JVM *myJvmPtr = (struct JVM*) myJvm;

    JavaVM *jvmPtr = myJvmPtr -> jvm;

    JNIEnv *env = myJvmPtr -> env;

    pthread_mutex_lock (&mutexjvm);

    printf("I will call JVM

    ");

    (*jvmPtr)->AttachCurrentThread(jvmPtr, (void**) &(env), NULL);

    invoke_class( env );

    (*jvmPtr)->DetachCurrentThread(jvmPtr);

    pthread_mutex_unlock (&mutexjvm);

    pthread_exit(NULL);

    }

    JNIEnv* create_vm(struct JVM *jvm)

    {

    JNIEnv* env;

    JavaVMInitArgs vm_args;

    JavaVMOption options;

    options.optionString = "-Djava.class.path=./";

    vm_args.options = &options;

    vm_args.ignoreUnrecognized = 0;

    vm_args.version = JNI_VERSION_1_6;

    vm_args.nOptions = 1;

    int status = JNI_CreateJavaVM(&jvm->jvm, (void**)&env, &vm_args);

    if (status < 0 || !env)

    printf("Error

    ");

    return env;

    }

    void invoke_class(JNIEnv* env)

    {

    jclass Main_class;

    jmethodID fun_id;

    Main_class = (*env)->FindClass(env, "Main");

    fun_id = (*env)->GetStaticMethodID(env, Main_class, "fun", "()I");

    (*env)->CallStaticIntMethod(env, Main_class, fun_id);

    }

    int main(int argc, char **argv)

    {

    struct JVM myJvm;

    myJvm.env = create_vm(&myJvm);

    if(myJvm.env == NULL)

    return 1;

    pthread_mutex_init(&mutexjvm, NULL);

    for(int i=0; i

    pthread_create(&threads[i], NULL, jvmThreads, (void*) &myJvm);

    pthread_join(threads[i], 0);

    }

    (*myJvm.jvm)->DestroyJavaVM(myJvm.jvm);

    }

    Main.java

    public class Main {

    public static void main(String[] args){

    System.out.println("Hello, world");

    }

    public static int fun() {

    System.out.println("From JVM");

    return 0;

    }

    }

    生成文件

    all: Main.class main

    Main.class: Main.java

    javac Main.java

    main.o: main.c

    llvm-gcc -c main.c \n -I${JAVA_HOME}/include \n -I${JAVA_HOME}/include/darwin/ \n

    main: main.o

    ld -o main -L${JAVA_HOME}/jre/lib/server/ \n -ljvm \n -rpath ${JAVA_HOME}/jre/lib/server \n -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk \n -demangle -dynamic -arch x86_64 \n -macosx_version_min 10.12.0 \n -lSystem \n -rpath ${JAVA_HOME}/jre/lib/server/ \n main.o

    clean:

    rm -f Main.class main main.o

    运行代码后,将得到以下结果:

    ./main

    I will call JVM

    From JVM

    I will call JVM

    From JVM

    I will call JVM

    From JVM

    I will call JVM

    From JVM

    I will call JVM

    From JVM

    I will call JVM

    From JVM

    展开全文
  • 我正在开发一个项目,在那里我用C++代码调用Java函数(使用JNI),我遇到了多线程问题.我想调用Java搜索功能,对于每个调用,我想创建一个单独的线程.我有一个单例MainClass和嵌套Query类.Queryclass继承自QThread.代码看...

    我正在开发一个项目,在那里我用C++代码调用Java函数(使用JNI),我遇到了多线程问题.我想调用Java搜索功能,对于每个调用,我想创建一个单独的线程.我有一个单例MainClass和嵌套Query类.Queryclass继承自QThread.代码看起来像这样

    MainClass::MyQuery query("");

    query.LaunchQuery();

    //functions of Query

    void MainClass::MyQuery::LaunchQuery() const

    {

    this->start();

    }

    void MainClass::Query::run()

    {

    const MainClass& mainClass = MainClass::GetInstance();

    const jclass& obj = mainClass.GetClass();

    JNIEnv& env = mainClass.GetJavaEnvironment();

    jmethodID methodId = env.GetMethodID(obj, "SearchQuery", "(Ljava/lang/String;)V"); //Run-time error

    if(methodId != 0)

    {

    //calling "SearchQuery" function

    }

    现在,如果在一个线程中运行此代码 - 一切都很好,但如果尝试运行上面的代码 - 使用多线程,"Unhandled exception at 0x777715de in MyApp.exe: 0xC0000005: Access violation reading location 0x000000ac."当我尝试获取方法ID时,它会导致运行时错误消息

    .我也试过boost::thread但结果是一样的.

    那么为什么当我在一个单独的线程中执行它时失败,当在同一个线程中一切都很好?有任何想法吗?

    展开全文
  • JNI封装调用另一个第三方算法so库,该SO库是能够支持多线程并发创建多个处理实例,同时处理数据的。则JNI在封装接口时,也需要注意接口方法并发的情况,这个时候必须尽可能使用局部变量,以免全局变量在某一线程中...

    本文章主要讲述的技巧为:Java层保存Native层中复杂数据的指针地址,Native需要时根据Java传递下来的地址重新强转回指针,以方便支持Java多线程并发创建多个对象进行调用。(即让每个对象能够保存属于自己的一份Native层数据"索引",必要时交由Native层去通过"索引"拿到数据进行处理)

    一、场景介绍

            在JNI开发过程有这样的一个场景:

            用JNI封装调用另一个第三方算法so库,该SO库是能够支持多线程并发创建多个处理实例,同时处理数据的。则JNI在封装接口时,也需要注意接口方法并发的情况,这个时候必须尽可能使用局部变量,以免全局变量在某一线程中被修改,导致在另一线程不能按预期执行。

            首先看下第三方so库的两个接口方法:

    /**
    * 创建对应token的算法处理实例,返回长度为inst_num的void型指针数组insts。
    * 此方法需支持并发创建不同token的实例
    */
    int create_instances(char* token, void **insts, size_t inst_num);
    
    /**
    * 使用insts数组中某一个inst实例去处理数据
    * 此方法同样支持并发
    */
    int process_data(void *inst, const int16_t *data, int data_size);

            从以上两个方法可以看出,第一个方法create_instances调用生成的insts指针数组,需要在执行第二个方法process_data用到,通过传入该数组的某个实例元素给第一个参数inst,以完成方法的调用。

    二、单线程封装的情况

            我们先来看下单线程下的简单情况处理,一般会想到使用一个全局变量来保存insts指针数组,在create_instances创建实例时为全局变量insts赋值,在process_data时直接拿到全局变量insts使用,如下:

    // 这里定义全局变量
    void ** insts;
    int inst_count;
    
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_test_Sample_native_1create_1instances(JNIEnv *env, jobject thiz, jstring token, const jint inst_num) {
    
        ...
        inst_count = inst_num;
        insts = static_cast<void **>(malloc(sizeof(void *) * inst_num));
        int create_ret = create_instances(token_chars, tokenLen, insts, inst_num);
        ...
    }
    
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_test_Sample_native_1process_1data(JNIEnv *env, jobject thiz, jint inst_seq, jbyteArray data, jint size) {
        ...
        jbyte *data_bytes = env->GetByteArrayElements(data, &isCopy);
        int16_t *data_int16 = (int16_t *) data_bytes;
        // 这里直接拿到全局变量insts进行使用
        int ret = process_data(insts[inst_seq], data_int16, size);
        env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
        return ret;
    }

    对应Java的native接口定义:

     public class Sample {
        
        public native int native_create_instances(String token, int inst_num);
        public native int native_process_data(int inst_seq, byte[] data, int size);
    
    }

    三、多线程封装的情况

            在多线程的情况下,上面的封装形式就没法支持并发,尽管不同线程new了各自的Sample对象,但实际不同线程在Native层仍然是执行了同一个代码块,共享了一个全局变量insts(这里需要注意,C语言并不像Java可以new对象,产生出多一份的实例堆内存,包含全局变量引用)。l例如token1的线程创建实例,之后token2的线程也创建实例,此时insts所指向的是token2的实例,token1的线程拿token2的insts去处理就会出现对应不上,导致报错。

           对于这种情况,我们可能很容易想到在C代码上维护一个加锁的容器,用来存放多个insts指针数组的,但这种方式用C语言实现起来较为麻烦,除了增加容器的增删查操作,还得注意加锁的正确性,而加锁也会导致降低一定的性能。

            再进一步思考能否让Sample对象对应保存自己创建insts指针数组,在create_instances时将insts数组传递上去,调用process_data在传递下来,这样就不存在不同线程创建各自Sample对象会共享一个C全局变量insts的问题。但是insts指针数组不像基本数据类型可以直接简单地值传递,我们也不知道元素void型指针具体指向的地址存放怎样的数据格式,这种传递行不通。但换个思路,可以通过传递指针数组的地址给Sample保存,调用时传递地址下来C层,C层在对地址进行强制类型转换。经过请教及实践,发现是行得通的,具体实现如下:

    Sample.java

    public class Sample {
    
        private long instAddress;   // 由JNI层进行赋值
        private int instNum;
        private int createResult = -1;
    
    
        private native int native_create_instances(String token, int instNum);
        private native int native_process_data(long inst_adress, int inst_seq, byte[] data, int size);
    
        public int createInstances(String token, int instNum) {
            this.instNum = instNum;
            // 这里调用返回成功后,Native层将给instAddress成员变量赋值
            createResult = native_create_instances(token, instNum);
            return createResult;
        }
    
        public int processData(int instSeq, byte[] data, int size) {
            if (createResult == -1) {
                System.out.println("error: create_instances ret != 0, please ensure instances is succeed before");
                return -1;
            }
            System.out.println("instAddress=" + instAddress);
            // 这里传递赋值过的成员变量instAddress,将指针数组地址传递给Native层
            return native_process_data(instAddress, instCnt, instSeq, data, size);
        }
    
    }

    主要改动:Sample类中新增了long型变量instAddress用以存储Native层传递的地址,在调用时数据处理时,并新增非Native方法processData将instAddress传递给本地native_process_data方法。

    Native层:

    // 全局引用保存Sample类class
    jclass globalSampleClass;
    
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_test_Sample_native_1create_1instances(JNIEnv *env, jobject thiz, jstring token, const jint inst_num) {
    
        ...
        // 给局部变量insts指针数组分配内存
        void **insts = static_cast<void **>(malloc(sizeof(void *) * inst_num));
        int create_ret = create_instances(data_chars, data_len, insts, inst_num);
    
        // 将insts数组指针地址保存到Java层的Sample对象的instAddress字段中,以便在其他函数使用
        if (create_ret == 0) {
            // 将insts指针数组的地址强制转换为long型数据
            long inst_address = reinterpret_cast<long>(insts);
            // 获得Sample的class引用
            if (NULL == globalSampleClass) {
                globalSampleClass = env->GetObjectClass(thiz);
            }
            // 获取Sample的成员变量instAddress的FiledID
            jfieldID instAddressField = env->GetFieldID(globalSampleClass, "instAddress", "J");
            // 给调用者Sample对象(thiz)的instAddress赋值
            env->SetLongField(thiz, instAddressField, inst_address);
        }
        // 注意不能销毁局部变量insts指针数组所指向的内存,其他函数还要用到
        ...
    }
    
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_test_Sample_native_1process_1data(JNIEnv *env, jobject thiz, jlong inst_address, jint inst_num, jint inst_seq, jbyteArray data, jint size) {
        ....
        jbyte *data_bytes = env->GetByteArrayElements(data, &isCopy);
        int16_t *data_int16 = (int16_t *) data_bytes;
        // 将long型地址数据强制转换为void **进行使用
        void **insts = (void **) inst_address;
        int ret = process_data(insts[inst_seq], data_int16, size);
        env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
        return ret;
    }

    主要改动:

    1. 去掉单线程情况下的两个全局变量,insts指针数组改为局部变量,将inst_count放到Java层存储,需要时传递下来;

    2. 保存void ** 型指针数组地址到Java层的long型变量,之前对传递下来的long型地址强制转换回void **。

    说明:局部变量insts所指向的内存最终会有另外一个销毁函数进行销毁,不是本文重点故忽略,实际开发需注意内存分配及释放,以免内存泄漏。

    四、总结

    关于JNI接口支持多线程的关键点:

    1. Native层不使用全局变量,能简单改为局部变量的直接改局部变量;

    2. Native必要的全局变量迁移到Java层进行保存,基础数据类型可以直接值传递,结构体数据或数组也可以采用传递地址的方式,将地址转换为long型数据传给Java对象,Native使用时再做强制转换。

    展开全文
  • 然而,在多线程的情况下, 可能出现以下问题:问题描述:一个java对象通过JNI调用DLL中一个send()函数向服务器发送消息,不等服务器消息到来就立即返回.同时把JNI接口的指针JNIEnv *env,和jobject...

    CSDN相关帖子::signal 11 (SIGSEGV), fault addr 0000015c是什么错误?怎么解决?

    java中要访问C++代码时, 使用JNI是唯一选择. 然而,在多线程的情况下, 可能出现以下问题:

    问题描述:

    一个java对象通过JNI调用DLL中一个send()函数向服务器发送消息,不等服务器消息到来就立即返回.同时

    把JNI接口的指针JNIEnv *env,和jobject obj保存在DLL中的变量里.

    一段时间后,DLL中的消息接收线程接收到服务器发来的消息,

    并试图通过保存过的env和obj来调用先前的java对象的方法来处理此消息.

    然而,JNI文档上说,JNI接口的指针JNIEnv*不能在c++的线程间共享,

    在我的程序中,如果接收线程试图调用java对象的方法,程序会突然退出.

    不知道有没有方法突破JNI接口的指针不能在多个c++线程中共享的限制?

    解决办法:

    http://java.sun.com/docs/books/jni/html/pitfalls.html#29161 提到,

    JNI接口指针不可为多个线程共用,但是java虚拟机的JavaVM指针是整个jvm公用的. 于是,在DLL中可以调用:

    static JavaVM* gs_jvm;

    env->GetJavaVM(&gs_jvm); 来获取JavaVM指针.获取了这个指针后,在DLL中的另一个线程里,可以调用:

    JNIEnv *env;

    gs_jvm->AttachCurrentThread((void **)&env, NULL);

    来将DLL中的线程 "attached to the virtual machine"(不知如何翻译...),同时获得了这个线程在jvm中的  JNIEnv指针.

    由于我需要做的是在DLL中的一个线程里改变某个java对象的值,所以,还必须获取那个java对象的jobject指针.同 JNIEnv 指针一样,jobject指针也不能在多个线程中共享. 就是说,不能直接在保存一个线程中的jobject指针到全局变量中,然后在另外一个线程中使用它.幸运的是,可以用

    gs_object=env->NewGlobalRef(obj);

    来将传入的obj保存到gs_object中,从而其他线程可以使用这个gs_object来操纵那个java对象了.

    示例代码如下:

    (1)java代码:Test.java:

    import java.io.*;

    class Test implements Runnable

    {

    public int value  = 0;

    private Thread tx=null;

    public Test()

    {

    tx=new Thread(this,"tx");

    }

    static

    {

    System.loadLibrary("Test");

    }

    public native void setEnev();

    public static void main(String args[])

    {

    Test t = new Test();

    t.setEnev();

    System.out.println("ok in java main");

    t.tx.start();

    try

    {

    Thread.sleep(10000000);

    }catch(Exception e)

    {

    System.out.println("error in main");

    }

    }

    public void run()

    {

    try

    {

    while(true)

    {

    Thread.sleep(1000);

    System.out.println(value);

    }

    }catch(Exception e)

    {

    System.out.println("error in run");

    }

    }

    }

    (2) DLL代码:Test.cpp:

    #include "test.h"

    #include

    #include

    static JavaVM *gs_jvm=NULL;

    static jobject gs_object=NULL;

    static int gs_i=10;

    void WINAPI ThreadFun(PVOID argv)

    {

    JNIEnv *env;

    gs_jvm->AttachCurrentThread((void **)&env, NULL);

    jclass cls = env->GetObjectClass(gs_object);

    jfieldID fieldPtr = env->GetFieldID(cls,"value","I");

    while(1)

    {

    Sleep(100);

    //在DLL中改变外面的java对象的value变量的值.

    env->SetIntField(gs_object,fieldPtr,(jint)gs_i++);

    }

    }

    JNIEXPORT void JNICALL Java_Test_setEnev(JNIEnv *env, jobject obj)

    {

    printf("come into test.dll/n");

    //Returns “0” on success; returns a negative value on failure.

    int retGvm=env->GetJavaVM(&gs_jvm);

    //直接保存obj到DLL中的全局变量是不行的,应该调用以下函数:

    gs_object=env->NewGlobalRef(obj);

    HANDLE ht=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFun,0,NULL,NULL);

    printf("the Handle ht is:%d/n",ht);

    }

    //====================================================================

    备注:

    1>JNI接口的指针JNIEnv*不能在c++的线程间共享

    2>同 JNIEnv 指针一样,jobject指针也不能在多个线程中共享

    3>每个native 函数传的jobject obj类其实就是相当于那个类的this指针

    //获取数组

    mid = (*env)->GetMethodID(env,cls,"getCanvasBmpByte","()[B");   //这里的最后一个参数是用javap -s -p 命令拿到的,很多文章有讲过

    msg = (jbyteArray)(*env)->CallObjectMethod(env,job, mid); //注意这里的第二个参数就是对象,意义就是你调用的是当前类的当前对象的这个方法,如果当前类没有这个函数那就直接出错了,如果你要在其他类里面调用这个方法,请把这个类的对象的引用做参数传递进来:

    Java_com_example_hellojni_HelloJni_InitGraphics( JNIEnv* env,jobject thiz ,jobject job )//这个就是函数所在的对象

    展开全文
  • 修改文如下:问题描述:一个java对象通过JNI调用DLL中一个send()函数向服务器发送消息,不等服务器消息到来就立即返回,同时把JNI接口的指针JNIEnv *env(虚拟机环境指针),和jobject obj保存在DLL中的变量里.一段时间后,...
  • I have a simple class in Java:public class MyClass{public static void dummyTest(){}}And in C++ I do the following JNI Call:void c_call_function(){JNIEnv *env ...// the JNIEnv initialization in JNI...j...
  • 一 .引入头文件 (注:不用添加 pthread.h 头文件)二 . 贴上 C++ 代码特别注意... 会报红,不必理会//当动态库被加载时这个函数被系统调用JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){JNIEnv* e...
  • 一、jni调用java对象JNI提供的功能之一是在本地代码中使用Java对象。包括:创建一个java类对象和通过函数传递一个java对象。创建一个java类对象,首先需要得到得到使用FindClass/GetObjectClass函数得到该类,然后...
  • jni函数传递进来的obj保存起来(或者在调用之前生成类对象:jobjectobj=(*env)->NewObject)2.获取类名:jclass cls =GetObjectClass(或者(*env)->FindClass)3.获取类方法:jmethodID mid = (*env)->...
  • 以下内容源于网络:... 然而,在多线程的情况下, 可能出现以下问题:问题描述:一个java对象通过JNI调用DLL中一个send()函数向服务器发送消息,不等服务器消息到来就立即返回.同时把JNI接口的指针JNIEnv *en...
  • 首先声明这个问题是在Android系统中进行之前在做NDK开发时,自然少不了workerThread = std::thread([this](){g_pVM->...并在线程中进行了Java方法的调用,传递了一些字符串,结果没跑几个循环进程就...
  • JNI多线程与全局引用

    2021-06-05 11:11:32
    之前的JNI学习文章《JNI异常处理和缓存策略》中有介绍过全局变量,在本文中将派上用用场,直接使用。本次实战主要是在C层开辟子线程,然后通过访问java类,获取得到UUID,并且打印出来。具体步骤:1、创建一个NDK...
  • JNI : Java Native Interface 即JAVA本地调用,为何需要这种技术呢?原因有二:1、运行JAVA程序的虚拟机是用Native语言编写的,而虚拟机运行在具体的平台上,所以虚拟机本身无法做到平台无关,而利用JNI技术即可对...
  • 1.Android JNI调用过程1.1 由Android系统加载的JNIAndroid系统在启动启动过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。Zygote启动过程中会AndroidRuntime....
  • 1. Java Native Interface介绍在以下的情况使用JNI:标准Java类库不支持的平台依赖特性的应用已经用其他语言编写好了一个库,希望用Java通过JNI访问你希望实现对时间效率要求严格的一小部分,比如用汇编通过本地接口...
  • java 多线程 出现数据重复调用问题线程操作过程描述:1、线程查询数据库表(table1)数据,并遍历修改记录状态(防止出现数据重复调用)。(此操作加入了同步锁)2、调用接口,获取返回的状态。3、把数据插入到数据库...
  • Java中多线程启动调用的是start()方法而不是run()方法 ​ 为什么多线程的启动不直接使用run()方法而必须使用Thread类中的start()方法呢?为什么调用的是start()方法,执行的确实run()方法呢? ​ 如果想要弄清楚这个...
  • 1. JNIEnv对象对于本地函数JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj){cout<...如,创建Java类得对象,调用Java对象的方法,获取Java对象的属性等。JNIEnv...
  • 背景:我的工作是C++,目前开发一个模块,针对java调用的,所以需要开发一个Jni动态库,暂定名字:"AJni.dll";这个动态库是依赖的是核心库“B.dll”还有用到mfc。开发完成用java测试时发现,当com包放在核心库目录...
  • 问题:我要用ndk编译c++的代码,其中包含了多线程,主线程和回调线程。在主线程中使用env->GetJavaVM(&g_jvm);得到了全局的vm,在回调线程中我首先得到了env:JNIEnv* env = NULL;g_jvm->...
  • 1 jni 1.1 jni简介 ...JNI是Java Native Interface的缩写,中文翻译Java本地接口, 也有译为Java本地调用。...JNI技术主要是完成Java代码与native代码进行交互,简单说就是用Java代码调用native语言编写的
  • } 1、编写java代码 MyThread.java 使用jni调用一个c程序,上传至/home/mythread/com/tigger/目录下 2、编译成class程序 javac MyThread.java 3、生成头文件 javah packageName.ClassName 此命令需要在包外执行,...
  • 1. C++ 全局调用Java方法1.1 C++主线程调用Java方法在 Android C++多线程-创建子线程中演示了在 Java 层调用 native 层的方法,但是如何在 native 层去调用 Java 层的方法呢?下面这个类,我们想在调用 ...
  • 当前位置:我的异常网» J2SE»JAVA调用DLL异常,请高手寻找异常原因,给出解决方法JAVA调用DLL异常,请高手寻找异常原因,给出解决方法www.myexceptions.net网友分享于:2013-09-05浏览:122次JAVA调用DLL错误,请...
  • cocos2d-x for Android 运行在多线程环境下,所以在 Lua/C++ 和 Java 交互时需要注意选择适当的线程。cocos2d-x 在 Android 上以两个线程来运行,分别是负责图像渲染的 GL 线程和负责 Android 系统用户界面的 UI ...
  • AndroidJNI异常崩溃

    2021-06-04 12:58:18
    在安卓下来会切换前后台有比较大概率崩溃,我们比较特殊的是会在两个线程里来回调用JNI接口(已经用了AndroidJNI.AttachCurrentThread)目前我定位到是在getMethodID的时候挂了,感觉是newString把className和method...
  • NDK编程中遇到的一些细节问题,希望对大家有帮助-----题记在JNI中,有时候出于业务要求需要实现异步事件机制,例如网络通讯的收发这时就会在C++中回调java类的方法,于是就会用到java反射机制在JNI中,实现类反射...
  • thread 而言是唯一的JNIEnv *env指针不可以为线程共用2、解决办法java虚拟机的JavaVM指针是整个jvm公用的,我们可以用JavaVM来得到当前线程的JNIEnv指针,可以使用javaAttachThread保证取得当前线程Jni环境...
  • 为了能在另外的线程调用Java的方法,需要在 .so 被加载时在 JNI_OnLoad 中提前保存 JavaVM 的地址到全局变量中,并且提前解析类和方法的id也都保存到全局变量中,等到异步线程开启之后,根据全局变量中存储的类和...
  • 到目前为止,我的几乎所有JNI线程同步都在Java端,答案显而易见:使用提供的Java并发包和内置的并发语言功能.不幸的是,答案在C方面并不那么明显.我到目前为止所尝试的内容我尝试使用pthreads互斥锁认为它可能会工作,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,170
精华内容 17,668
关键字:

多线程调用jni