2012-06-15 27 views
7

Tamam, bu yüzden aşağıda yerel kod var. Stat() ile döndürülen bazı verilerle doldurulmuş bir FilePermissionInfo dizisini döndürmeye çalışıyorum.NewObject çağrısında geçersiz dolaylı başvuru

06-15 20: 25: 17.621: dalvikvm/W (2287): sorun NewObject ilk kez olarak adlandırılır aşağıdaki hatayı elde edilmesi geçersiz dolaylı referans 0x40005820 decodeIndirectRef 06-15 bölgesindeki 20: 25: 17,621: E/dalvikvm (2287): ben sadece referans nesnesi (FilePermissionInfo için) jclass çünkü VM,

tuhaf

iptal ve ben küresel bir referansa çevirin.

kodudur:

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 sınıfı yapıcısı imza ve yol şunlardır:

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

Sonra varsayılan yapıcı NewObject çağırırsanız çalıştığını unutmayınız ince.

+0

Gerçekten bu NDK (v8) bir hata değildir umarım. Her türlü yaklaşımı denedim ve varsayılan kurucu (yani "() V" ile çalıştığı için çok tuhaftır. Nihayetinde değerleri ayarlamak için bu sınıftaki dizileri kullanabilirim, ancak çağırmak istemem JNI sınırı üzerinde çok fazla yöntem var demektir –

cevap

13

Tamam, onu buldum. jstring parametreleriyle ilgili bir sorun oldu. Boş dizeleri (veya bu konu için NULL) jstring olarak geçemezsiniz. Bunun yerine NULL jstring oluşturmak için (*env)->NewStringUTF(env, NULL) kullandım.

Şimdi işe yarıyor görünüyor.


Bu soru bir şekilde yüksek bir etkinlik oluşturduğundan, son çözümü aşağıda gönderiyorum. nullString değişken (bunu kullanmayı bitirdiğinizde ya da) kapsamı sonunda ayırmanın unutmayın:

 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); 
+2

'' '', '', '(* env) -> NewObject (...)' işlevindeki argümanları 'jstring myNullString = (* env) -> NewStringUTF (env, NULL) 'sonra argüman olarak myNullString iletin? –

+1

@ m-ric: Evet, bu doğru. –

+0

Bunun orijinal olarak belirtildiği gibi boş jstring'lerle ilgili bir sorun olduğundan emin değilim. Bu konuya koşuyordu, ancak aşağıdaki gibi bir şeyi kullanarak düzeltmeyi başardı: std: string empty (""); jstring myemptyString = (* env) -> NewStringUTF (empty.c_str()) Not: Android ile test ediyordum 4.3. –