나는 C에서 Java로 호출하는 JNI 호출 API에서 작업 중이다. 전역 참조로 30+ Java 클래스를 캐시하기위한 몇 가지 초기 초기화가있다. FindClass의 결과는 NewGlobalRef에 전달되어 클래스에 대한 전역 참조를 가져옵니다. 나중에이 클래스 변수를 캐싱하여 나중에 다시 사용합니다. 클래스에 30 개 이상의 전역 참조가 있고 클래스 생성자에 대해 30 개 이상의 전역 methodID가 있습니다.JNI 캐시 된 jclass 전역 참조 변수가 가비지 수집됩니까?
다음 샘플에서는 코드 단편을 줄이기 위해 예외 처리와 JNI 호출을 제거했습니다. 내 작업 코드는 모든 JNI 호출 후에 예외 검사를하고 -Xcheck : jni를 사용하여 실행합니다. 여기 단편이다 :
jclass aClass;
jclass bClass;
jmethodID aCtor;
jmethodID bCtor;
void getGlobalRef(const char* clazz, jclass* globalClass)
{
jclass local = (*jenv)->FindClass(jenv,clazz);
if (local)
{
*globalClass = (jclass) (*jenv)->NewGlobalRef(jenv,local);
(*jenv)->DeleteLocalRef(jenv,local);
}
}
methodID getMethodID(jclass clazz, const char* method, const char* sig)
{
return (*jenv)->GetMethodID(jenv,clazz,method,sig);
}
void initializeJNI()
{
getGlobalRef("MyProj/Testclass1", &aclass);
getGlobalRef("MyProj/Testclass2", &bclass);
.
.
aCtor = getMethodID(aclass,"<init>","()V");
bCtor = getMethodID(bclass,"<init>","(I)V");
}
initializeJNI() 함수는 생성자뿐만 아니라 일부 jfieldID는 C의 및 데이터 구조의 일부 초기화 jclasses 방법 및 ID의 전역 참조를 설정한다.
캐시 된 jclass와 ctor jmethodID 중 일부를 사용하여 JNI 함수를 호출하면 초기화 된 후에 -Xcheck : jni에서보고 된 잘못된 전역 또는 로컬 참조 호출이 발생합니다.
gdb에서 initializeJNI()의 마지막 줄에서 깨지고 모든 jclasses와 jmethodIDs를 인쇄하면 문제를 일으키는 원인이 가비지 수집되거나 가비지 수집 (예 : 0x00 또는 0x06) 된 것으로 보입니다. 글로벌 참조가 가능할 수 있습니까?
제안 사항?
해결되었습니다. C.의 데이터 손상 JNI 오류가 없습니다. – bubbadoughball