我想使用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线程的某些限制,我需要注意。我希望代码可以同时作为函数和线程进行调用。
答案 0 :(得分:0)
我无法具体说明为什么您的本机方法似乎在GetObjectClass
调用中失败,但是更一般而言,您的本机方法存在严重缺陷。具体来说,
JNI接口指针仅在当前线程中有效。因此,本机方法不得将接口指针从一个线程传递到另一个线程。
(JNI Specifications, chapter 2)
您正是在执行该规定所禁止的活动。本机方法可以创建新的本机线程(尽管我不建议这样做),但是只有JVM调用本机方法的线程可以出于任何原因以任何方式访问JNI环境指针。
这个问题可能足以解释您观察到的行为,但是即使真正的解释是其他内容,在这一点上也不值得深入研究,因为本机方法需要全面重写,甚至可能需要重新设计。 / p>