JNI 학습 노트 - JAVA 대상과 내부 클래스를 만들 때 주의해야 합니다

4224 단어
기본 형식과 기본 형식 그룹의 구덩이를 넘어서 대상과 대상형 데이터 (String 포함) 로 들어갑니다.
String 클래스의 기본 동작은 전송에서 전송에 이르기까지 인터넷에서 셀 수 없이 많은데 관건은 자원의 방출과 회수, 그리고 용량 오류 처리에 있다
jobjectArray Java_com_smile_jnitest_JNITest_sort
  (JNIEnv *env, jclass, jobjectArray strs){
	int size = env->GetArrayLength(strs);
	const char* ns[size];
	jclass jc = env->FindClass("java/lang/String");
	jobjectArray result = env->NewObjectArray(size,jc,0);
	for (int i = 0; i < size; ++i) {
		jobject job = env->GetObjectArrayElement(strs,i);
		jstring str = (jstring)job;
		int size = env->GetStringUTFLength(str);
		const char* cs = env->GetStringUTFChars(str,NULL);
		/*  , , 
		 * ns[i] = cs;
		 *  , , , 
		 */
		jstring js = env->NewStringUTF(cs);
		env->SetObjectArrayElement(result,i,js);
		env->ReleaseStringUTFChars(str,cs);
	}
	return result;
}
부딪치는 것도 테스트를 완성한 셈이지만, 인코딩 문제와 유형 전환 문제는 아직 깊이 들어가야 한다.
String이라는 간단한 대상을 완성하고 복잡한 사용자 정의 대상으로 출발합니다.
유감스럽게도 저는 처음부터 현명하지 못한 시작을 선택했습니다. 사용자 정의 내부 클래스입니다.
첫 번째 코드:
jobject	Java_com_smile_jnitest_JNITest_testObj
	(JNIEnv *env, jclass c, jint x, jstring y){
	// class 
	jclass jc = env->FindClass("com/smile/jnitest/JNITest$TestPoint");
	// ID( , , )
	jmethodID jmi = env->GetMethodID(jc,"","()V");
	jmethodID jmiSetX = env->GetMethodID(jc,"setX","(I)V");
	jfieldID jfiY = env->GetFieldID(jc,"y","Ljava/lang/String");
	jmethodID jmiGetY = env->GetMethodID(jc,"getY","()Ljava/lang/String");
	jobject testPoint = env->NewObject(jc,jmi);
	env->CallVoidMethod(testPoint,jmiSetX,x);
	env->SetObjectField(testPoint,jfiY,y);
	jstring getString = (jstring)env->CallObjectMethod(testPoint,jmiGetY);
	const char* preStr = env->GetStringUTFChars(getString,NULL);
	char* endStr = "cao";
	char *newStr = NULL;
	int	nLen = strlen(preStr) + strlen(endStr);
	newStr = new char[nLen+1];
	memset(newStr,0,nLen+1);
	strcat(newStr,preStr);
	strcat(newStr,endStr);
	// UTF8
	newStr[nLen] = '\0';
	jstring newJstr = env->NewStringUTF(newStr);
	env->SetObjectField(testPoint,jfiY,newJstr);
	env->ReleaseStringUTFChars(getString,preStr);
	return testPoint;
}
이상 코드가 뛰기 시작하면 틀림없이 다운될 것이다. 타당하다. 두 가지 오류를 범했기 때문이다.
1: 매개변수 서명 - Signature에서 기본 유형이 아닌 클래스 객체 서명 형식을 L+ 클래스의 전체 이름(패키지 이름 포함)+로 지정합니다.눈도 없고 눈도 없는 내가 빠뜨렸다";,나는 그것을 보지 못했기 때문이다.
2: JAVA에서 내부 클래스를 만드는 대상은 어떻게 만듭니까?내부류는 외부의 주류에 의존하여 생존한다. 아버지가 없으면 자식이 없다는 것을 이해할 수 있다. 내부류를 만들려면 먼저 외부의 주류를 만들어야 한다.
따라서 그 구조 함수는 반드시 외부 주 클래스에 전송되어야 하고javap-s 명령을 사용해도 조회할 수 있다. 이 내부 클래스의 구조 서명은signature: (L 외부 주 클래스)V
원인을 찾아 수정된 코드:
jobject	Java_com_smile_jnitest_JNITest_testObj
	(JNIEnv *env, jclass c, jint x, jstring y){
	// class 
	jclass jc = env->FindClass("com/smile/jnitest/JNITest$TestPoint");
	// ID( , , )
	jmethodID jmi = env->GetMethodID(jc,"","(Lcom/smile/jnitest/JNITest;)V");
	jmethodID jmiSetX = env->GetMethodID(jc,"setX","(I)V");
	jfieldID jfiY = env->GetFieldID(jc,"y","Ljava/lang/String;");
	jmethodID jmiGetY = env->GetMethodID(jc,"getY","()Ljava/lang/String;");
	// 
	jmethodID pjmi = env->GetMethodID(c,"","()V");
	// 
	jobject pointParent = env->NewObject(c,pjmi);
	// 
	jobject testPoint = env->NewObject(jc,jmi,pointParent);
	env->CallVoidMethod(testPoint,jmiSetX,x);
	env->SetObjectField(testPoint,jfiY,y);
	jstring getString = (jstring)env->CallObjectMethod(testPoint,jmiGetY);
	const char* preStr = env->GetStringUTFChars(getString,NULL);
	char* endStr = "cao";
	char *newStr = NULL;
	int	nLen = strlen(preStr) + strlen(endStr);
	newStr = new char[nLen+1];
	memset(newStr,0,nLen+1);
	strcat(newStr,preStr);
	strcat(newStr,endStr);
	// UTF8
	newStr[nLen] = '\0';
	jstring newJstr = env->NewStringUTF(newStr);
	env->SetObjectField(testPoint,jfiY,newJstr);
	env->ReleaseStringUTFChars(getString,preStr);
	return testPoint;
}
이로부터 완전, 대상이 호출한 오점 공격, 다음 단계로 진입

좋은 웹페이지 즐겨찾기