JNI 학습 노트 - JAVA 대상과 내부 클래스를 만들 때 주의해야 합니다
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;
}
이로부터 완전, 대상이 호출한 오점 공격, 다음 단계로 진입
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.