2012-06-15 7 views
7

OK, así que tengo el código nativo a continuación. Estoy tratando de devolver una matriz de FilePermissionInfo, rellenada con algunos datos devueltos por stat(). El problema es que me sale el siguiente error al NewObject se llama la primera vez:Referencia indirecta no válida en la llamada a NewObject

06-15 20: 25: 17.621: W/dalvikvm (2287): no válida referencia indirecta 0x40005820 en decodeIndirectRef 06-15 20: 25: 17.621: e/dalvikvm (2287): VM abortando

es extraño, porque el único objeto de referencia que tengo es los jclass (por FilePermissionInfo) y convertirla a una referencia mundial.

El código es:

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; 

}

El Java firma constructor de la clase y la ruta son:

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

Tenga en cuenta que si llamo NewObject en el constructor por defecto entonces funciona multa.

+0

Realmente espero que esto no es un error en el NDK (v8). He intentado todo tipo de enfoques y es muy extraño que funcione con el constructor predeterminado (es decir, "() V". En última instancia, puedo usar los setters en esa clase para establecer los valores, pero no me gustaría invocar demasiados métodos sobre el límite JNI. –

Respuesta

13

OK, lo encontramos. Hubo un problema con los parámetros jstring. Resulta que no puede pasar cadenas vacías (o incluso NULL para ese asunto) como jstring. En su lugar utilicé (*env)->NewStringUTF(env, NULL) para crear un NULL jstring.

Parece que funciona bien ahora.


Dado que esta pregunta generó una gran actividad, estoy publicando la solución final a continuación. Tenga en cuenta que la variable nullString se cancela la asignación al final de su ámbito de aplicación (o cuando haya terminado de usarlo):

 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

¿Quiere decir que reemplazó los argumentos '" "," ",' en la llamada a función '(* env) -> NewObject (...)' en un 'jstring myNullString = (* env) -> NewStringUTF (env, NULL) 'luego pasa myNullString como argumentos? –

+1

@ m-ric: Sí, eso es correcto –

+0

No estoy seguro de que esto siga siendo un problema con jstrings vacíos, como se dijo originalmente. se estaba metiendo en este problema, pero fue capaz de arreglarlo usando algo como: std: string empty (""); jstring myemptyString = (* env) -> NewStringUTF (empty.c_str()); Tenga en cuenta que estaba probando con android 4.3. –

Cuestiones relacionadas