2011-07-18 2 views
4

JNI에서 전체 bytearray를 참조 할 수는 있지만 사본을 호출 할 수 있습니까?JNI에서 bytearray를 읽는 방법?

네이티브 C 코드에서 저는 자바에서 패스 한 bytearray를 가지고 있습니다. 그리고 저는 일부 데이터를이 bytearray와 비교하기를 원하므로 어떤 메모리 복사본도 원하지 않습니다. 가능한가?

는 내가 얻을 GetPrimitiveArrayCritical에 사용해야합니다, 당신이 볼 수있는 것처럼 나는 jbIn의 데이터를 변경할 수 있기 때문에, 그

JNIEXPORT jbyteArray JNICALL Java_nfore_android_bt_pro_nfhfp_dsp 
(JNIEnv *env, jobject jobj, jbyteArray jbIn, jbyteArray jbBase){ 

    jbyte *bufferIn; 
    jbyte *bufferBase; 
    bufferIn = (*env)->GetPrimitiveArrayCritical(env, jbIn, NULL); 

    LOGD("Begin of dsp()"); 
    LOGD("In dsp() Before Comparing..."); 

     // Compare bufferIn with bufferBase here... 

    LOGD("In dsp() After Comparing..."); 
    LOGD("End of dsp()"); 

    (*env)->ReleasePrimitiveArrayCritical(env, jbIn, bufferIn, 0); 

    return jbIn; 
} 

같은 GetPrimitiveArrayCritical에 뭔가를 사용하여 네이티브 ByteArray에의 포인터를 얻을 수 알고 포인터를 놓고 나중에 놓으십시오.

그러나 bytearray jbBase를 읽으려면 jbBase의 포인터를 가져올 수 있지만 GetPrimitiveArrayCritical을 사용하지 않는 방법은 무엇입니까?

의견을 보내 주시면 감사하겠습니다. 고마워.

답변

9

나는

jbyte *b = (jbyte *)env->GetByteArrayElements(jbBase, NULL); 
// read bytes in *b here 
... 
// release it 
env->ReleaseByteArrayElements(jbBase, b, 0); 

당신은 아직도 당신이 아직도 그것을 사용하는 동안 가비지 컬렉터가 잠재적으로 치우는 정지로 해제 할 필요가 ... 바이트 배열을 읽고 다음을 사용합니다.

+0

답장을 보내 주셔서 감사합니다. Jim. 스펙 가이드에 따르면, GetByteArrayElements는 여전히 copy를 할 것입니다, 맞습니까? 게다가, GetByteArrayElements가이 bytearray에 독점 모드를 설정하겠습니까? 다른 스레드에서이 bytearray를 동시에 읽어야 할 경우 충돌이 발생합니까? 감사. –

+2

독점 모드는 설정하지 않지만 배열을 읽는 중이라면 동시 액세스가 정상적으로 이루어져야합니다. 동시에 쓸 수 있으면 뮤텍스를 사용하거나 동기화해야합니다. 그것이 복사를한다면, 배열에 포인터를 반환한다고 말할 수 있을지 모르겠다. 고성능 코덱으로 사용하고 배열을 복사하는 것을 결코 눈치 채지 못했다. 그것은 사본을했다. –

+0

좋아, 알았다. 도와 주셔서 감사합니다 Jim. –

6

GetByteArrayElements 메서드는 프로그램에서 참조 또는 복사본을 사용할 수 있다고 보장 할 수 없습니다. JNI는 오브젝트를 카피 한 상태 또는 핀 된 상태의 isCopy 플래그를 돌려줍니다 (핀은 참조를 의미). 결코 복사하지 않으려면 GetArrayElements 메소드를 사용하지 않아야합니다. 왜냐하면 항상 사본을 반환하기 때문입니다 (JVM은 사본을 결정하거나 복사하지 않을 것이고 복사는 가비지 수집기의 부담을 덜어주기 때문에 복사를 선호 할 수 있습니다). 나는 그것을 시도하고 큰 배열을 보냈을 때 나의 숫양이 증가한 것을 보았다. 문서가 말한대로 해당 때까지 가비지 컬렉션을 사용하지 않도록 설정, GetPrimitiveArrayCritical에 자바 배열의 직접적인 힙 주소를 반환,

IBM copy and pin

(트리 뷰에서 복사 및 핀 주제를 보면) : 당신은 또한에서 아래 링크를 볼 수 있습니다 ReleasePrimitiveArrayCritical이 호출됩니다. 따라서 GetPrimitiveArrayCritical을 사용해야합니다 (큰 배열을 가지고있을 때 필요합니다). 우리는 당신의 코드를 보면, 당신이 아래의 하나에 의해 배열을 얻을 수 있습니다 (난 당신이 JNI 함수에하는 jobject로 int 배열을 보내 가정) :

length = (*env)->GetArrayLength(jbIn); 
bufferIn = (*env)->GetPrimitiveArrayCritical(env, jbIn, NULL); 
for(int i=0; i<length; i++) 
    printf("Value of jbIn[%d]: %d", i, bufferIn[i]); 
(*env)->ReleasePrimitiveArrayCritical(env, jbIn, bufferIn, 0); 

중요 참고 : JNI은 '아무튼 때문에 GetPrimitiveArrayCritical에 후주는 GetArrayLength 수 없습니다 get과 critical 메소드 사이에서 동일한 객체에 대한 JNI 함수를 호출 할 수있게 허용한다.

관련 문제