3

NDK を使用して、Java に大きなバッファを割り当てます。

allocNativeBuffer(JNIEnv* env, jobject cls, jlong size) {
    void* buffer = malloc(size);
    jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
    jobject globalRef = env->NewGlobalRef(directBuffer);
    return globalRef;
}

このバッファを使用した後、割り当てを解除します。

freeNativeBuffer(JNIEnv* env, jobject cls, jobject globalRef) {
    void *buffer = env->GetDirectBufferAddress(globalRef);
    env->DeleteGlobalRef(globalRef);
    free(buffer);
}

Android 2.2 では問題なく動作しますが、Android 4.0.3 では DeleteGlobalRef 呼び出し中にアプリケーションがクラッシュします。私は何を間違っていますか?

4

1 に答える 1

1

グローバル参照とローカル参照の実装は、Java 側でのメモリ管理を改善する目的で、ICS で完全に見直されました。開発者ガイドで説明を見つけてください。開発者ブログで詳細を読んでください。

globalRef簡単に言えば、関数のパラメーターを含め、JNI 関数で受け取るものはfreeNativeBuffer()すべてローカル参照です。次のように、C コードでグローバル参照を作成して保持できます。

static jobject globalRef;

allocNativeBuffer(JNIEnv* env, jobject cls, jlong size) {
    void* buffer = malloc(size);
    jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
    globalRef = env->NewGlobalRef(directBuffer);
    return directBuffer;
}

freeNativeBuffer(JNIEnv* env, jobject cls, jobject localRef) {
    void *buffer = env->GetDirectBufferAddress(localRef);
    if (buffer == env->GetDirectBufferAddress(globalRef) {
        /* we received the object that we saved */
        env->DeleteGlobalRef(globalRef);
        free(buffer);
    }
}

PS私はあなたの実験のインスピレーションのように見えるstackoverflowの議論を見つけました。そもそもグローバル参照を作成および削除する必要がなかったことを説明する回答を参照してください。

于 2012-10-10T12:58:39.677 に答える