无法访问c ..中线程内的jclass已上传代码

时间:2019-03-25 11:31:08

标签: c java-native-interface

我想使用JNI从C更新一个Java的易失FLAG值,并且我正在基于Java中已更改的FLAG值进行一些处理。如果我不使用线程调用callit函数,则上传的代码可以正常工作。对于else子句工作正常,我将其称为普通函数。 但是当我使用线程调用此函数时,它崩溃了,并且发生在我尝试获取Jclass对象的那一行。

        #include <jni.h>
        #include<stdio.h>
        #include "JNIDemoJava.h"
        #include "Bridge.h"
        #include<malloc.h>
        #include<time.h>
        #include<pthread.h>
        #include<math.h>
        float Data_Q[8192*8192];
        float Data_I[8192*8192];
        float Data_Q1[8192*8192];
        float Data_I1[8192*8192];


        struct send_data

        {

            float *data;

            int index;

           const char *fname;

        }*a,*b;





        struct call_it

        {

        const char* fname1;

        const char *fname2;

        int ind;

        int scale_factor;

        float *Parameter;

        float *Data_I;

        float* Data_Q;

        int* Data_out;

        JNIEnv * jenv;

        jobject jobj;

        }



        JNIEXPORT jintArray JNICALL Java_jnidemojava_Main_nativePrint(JNIEnv  * env,jobject obj, jstring s1, jstring s2,jint ind,jint scale_factor,jfloatArray Params,jintArray jdata,jfloatArray DataI,jfloatArray DataQ,jobject job)

        {

                jintArray arr;

                pthread_t thread1,thread2,thread3;

                int i=0,t1=0,t2=0,t3=0,indx=0;

                jclass cls = (*env)->GetObjectClass(env,obj);

                int *data = (*env)->GetIntArrayElements(env,jdata,NULL);

            int * adata = (*env)->GetDirectBufferAddress(env,job);

            float *Parameters = (float*)malloc(sizeof(float)*13);
            Parameters = (*env)->GetFloatArrayElements(env,Params,NULL);

            const char *fname1,*fname2;

            fname1 = (*env)->GetStringUTFChars(env,s1,NULL);

            fname2 = (*env)->GetStringUTFChars(env,s2,NULL);

            printf("Value of ind = %d",ind);

            for(indx=0;indx<ind;indx++)

            {

            struct call_it  *asd= (struct call_it*)malloc(sizeof(struct call_it));

            asd->ind =   indx;

            asd->Data_I = Data_I;

            asd->Data_Q= Data_Q;

            asd->fname1= fname1;

            asd->fname2  = fname2;

            asd->scale_factor = scale_factor;

            asd->Data_out = adata;

            asd->Parameter = Parameters;

            asd->jenv = env;

            asd->jobj = obj;


            if(Parameters[12] ==1)

            {



        a= (struct send_data *)malloc(sizeof(struct send_data));

        b= (struct send_data *)malloc(sizeof(struct send_data));
        a->index = b->index = indx;

        a->data = Data_I;

        b->data = Data_Q;

        a->fname = fname1;

        b->fname = fname2;

        t1= pthread_create(&thread1, NULL, maini, (void*) a);

        t2= pthread_create(&thread2, NULL, mainq, (void*) b);

        pthread_join(thread1,NULL);

        memcpy(Data_I1,Data_I,sizeof(float)*8192*8192);

        pthread_join(thread2,NULL);

        memcpy(Data_Q1,Data_Q,sizeof(float)*8192*8192);

        asd->Data_I = Data_I1;

        asd->Data_Q = Data_Q1;

        t3= pthread_create(&thread3, NULL, callit, (void*) asd);
        //pthread_join(thread3,NULL);

            }

            else

            {

                 callit(asd);

            }


            free(asd);

            free(a);

            free(b);

            }

            return arr;





        }



        void*  callit(void *b) {

           struct call_it *asd = (struct call_it*)b;



            JNIEnv *env=asd->jenv;

            jobject obj= asd->jobj;

            jclass cls = (*env)->GetObjectClass(env,obj);//crashes at this point


            jfieldID fidnum = (*env)->GetStaticFieldID(env,cls,"FLAG","I");

            if(fidnum==NULL)

                {

                    printf("-----------_Error________________");

                    return;

                }

                jint num = (*env)->GetStaticIntField(env,cls,fidnum);



            process_data(b);



              num =asd->ind;

             (*env)->SetStaticIntField(env,cls,fidnum,num);



        }

根据我的理解,它在两种情况下都应该工作正常。如果不是这样,则必须注意c线程的某些限制,我需要注意。我希望代码可以同时作为函数和线程进行调用。

1 个答案:

答案 0 :(得分:0)

我无法具体说明为什么您的本机方法似乎在GetObjectClass调用中失败,但是更一般而言,您的本机方法存在严重缺陷。具体来说,

  

JNI接口指针仅在当前线程中有效。因此,本机方法不得将接口指针从一个线程传递到另一个线程。

JNI Specifications, chapter 2

您正是在执行该规定所禁止的活动。本机方法可以创建新的本机线程(尽管我不建议这样做),但是只有JVM调用本机方法的线程可以出于任何原因以任何方式访问JNI环境指针。

这个问题可能足以解释您观察到的行为,但是即使真正的解释是其他内容,在这一点上也不值得深入研究,因为本机方法需要全面重写,甚至可能需要重新设计。 / p>