7

OK、それで私は以下のネイティブコードを持っています。stat()によって返されたデータが入力されたFilePermissionInfoの配列を返そうとしています。問題は、NewObjectが最初に呼び出されたときに次のエラーが発生することです。

06-15 20:25:17.621:W / dalvikvm(2287):decodeIndirectRefの無効な間接参照0x40005820 06-15 20:25:17.621:E / dalvikvm(2287):VMが異常終了

私が持っている唯一の参照オブジェクトはjclass(FilePermissionInfo用)であり、それをグローバル参照に変えるので、それは奇妙です。

コードは次のとおりです。

JNIEXPORT jobjectArray JNICALL
Java_com_mn_rootscape_utils_NativeMethods_getFilesPermissions( JNIEnv* env, jobject thizz, jobjectArray filePathsArray ) 
{
jobjectArray result;
int size = (*env)->GetArrayLength(env, filePathsArray);
jboolean isCopy;

jclass filePermInfoCls = (*env)->FindClass(env, kFilePermissionInfoPath);
if(!filePermInfoCls)
{
    LOGE("getFilesPermissions: failed to get class reference.");
    return NULL;
}

gFilePermInfoClass = (jclass)(*env)->NewGlobalRef(env, filePermInfoCls);
LOGI("got gFilePermInfoClass");

jmethodID filePermInfoClsConstructor = (*env)->GetMethodID(env, gFilePermInfoClass, "<init>", kFilePermInfoConstructorSig);
if(!filePermInfoClsConstructor)
{
    LOGE("getFilesPermissions: failed to get method reference.");
    return NULL;
}

struct stat sb;

LOGI("starting...");
result = (jobjectArray)(*env)->NewObjectArray(env, size, gFilePermInfoClass, NULL);
for(int i = 0; i != size; ++i) 
{
    jstring string = (jstring) (*env)->GetObjectArrayElement(env, filePathsArray, i);
const char *rawString = (*env)->GetStringUTFChars(env, string, &isCopy);    

    if(stat(rawString, &sb) == -1) 
    {
        LOGE("stat error for: %s", rawString);
    }

    LOGI("%ld %ld %ld %ld %ld %ld %ld %ld", sb.st_dev, sb.st_mode, sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_atime, sb.st_mtime, sb.st_ctime);

    jobject permInfo = (*env)->NewObject(env, 
                            gFilePermInfoClass, 
                            filePermInfoClsConstructor, 
                            (long)sb.st_dev,
                            (long)sb.st_mode,
                            (long)sb.st_nlink,
                            (long)sb.st_uid,
                            (long)sb.st_gid,
                            (long)sb.st_atime,
                            (long)sb.st_mtime,
                            (long)sb.st_ctime,
                            "",
                            "",
                            1,
                            "");

    LOGI("xxx1");
    (*env)->SetObjectArrayElement(env, result, i, permInfo);
    LOGI("xxx2");
    (*env)->ReleaseStringUTFChars(env, string, rawString);
    LOGI("xxx3");
}

(*env)->DeleteLocalRef(env, filePermInfoCls);

return result;

}

Javaクラスコンストラクタの署名とパスは次のとおりです。

const char* kFilePermissionInfoPath = "com/mn/rootscape/utils/FilePermissionInfo";
const char* kFilePermInfoConstructorSig = "(JJJJJJJJLjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V";

デフォルトのコンストラクターでNewObjectを呼び出すと、正常に機能することに注意してください。

4

1 に答える 1

13

OK、見つけました。jstringパラメータに問題がありました。空の文字列(さらに言えばNULL)をとして渡すことはできませんjstring。代わりに、私(*env)->NewStringUTF(env, NULL)はNULLを作成していましたjstring

今は問題なく動作しているようです。


この質問はやや高い活動を生み出したので、私は以下に最終的な解決策を投稿します。nullString変数はスコープの最後で(または使用が終了したときに)割り当て解除されていることに注意してください。

        jstring nullString = (*env)->NewStringUTF(env, NULL);
...
        jobject permInfo = (*env)->NewObject(env, 
                                gFilePermInfoClass, 
                                filePermInfoClsConstructor, 
                                (jbyte)permsOwner,
                                (jbyte)permsGroup,
                                (jbyte)permsOthers,
                                (jlong)sb.st_uid,
                                (jlong)sb.st_gid,
                                (jlong)sb.st_atime,
                                (jlong)sb.st_mtime,
                                (jlong)sb.st_ctime,
                                nullString,
                                nullString,
                                (jboolean)1,
                                nullString);
...
       (*env)->DeleteLocalRef(env, nullString);
于 2012-06-16T21:01:11.343 に答える