2010-09-02 14 views
15

Ho un problema simile a this question, ma leggermente diverso. Ho compilato una libreria .so da utilizzare con JNI. Poiché è grande (15 MB), lo metto sulla SDCard invece che nella posizione dell'applicazione standard.Android - errore nel caricamento della libreria

Il file si chiama libSample.so e si trova a /data/library/libSample.so

lo carico in un blocco di inizializzazione statico:

try { 
     File sdcard = Environment.getExternalStorageDirectory(); 
     File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample.so"); 
     Log.i("Library", "Does the library exist?" + libraryLoc.exists()); 

     System.load(libraryLoc.getAbsolutePath()); 
    } 
    catch (UnsatisfiedLinkError e) { 
     Log.e("Translator", e.getMessage()); 
     Log.e("Translator", e.toString()); 
    } 

Ecco l'output logcat rilevanti:

09-02 16:42:58.882: DEBUG/dalvikvm(4185): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:42:58.892: DEBUG/dalvikvm(4185): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:42:58.892: DEBUG/dalvikvm(4185): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:42:58.892: INFO/Library(4185): Library exists: true 
09-02 16:42:58.902: INFO/Library(4185): Library can be read: true 
09-02 16:42:58.902: DEBUG/dalvikvm(4185): Trying to load lib /sdcard/library/libSample.so 0x434fb6f8 
09-02 16:42:58.902: INFO/dalvikvm(4185): Unable to dlopen(/sdcard/library/libSample.so): Cannot find library 
09-02 16:42:58.912: ERROR/Translator(4185): Library /sdcard/library/libSample.so not found 
09-02 16:42:58.912: ERROR/Translator(4185): java.lang.UnsatisfiedLinkError: Library /sdcard/library/libSample.so not found 

Qualsiasi idea cosa c'è che non va?

Ho letto il post su can android load dll's from sdcard in native mode che diceva che la sdcard non può essere utilizzata per caricare le librerie, quindi ho spostato il file .so in /data/data/com.example.hellojni/lib/libSample.so (i dati dell'app privati posizione di stoccaggio). Nessun cambiamento:

09-02 16:53:18.332: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:53:18.342: DEBUG/dalvikvm(4515): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:53:18.342: DEBUG/dalvikvm(4515): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8 
09-02 16:53:18.352: INFO/Library(4515): Library exists: true 
09-02 16:53:18.352: INFO/Library(4515): Library can be read: true 
09-02 16:53:18.352: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libSample.so 0x434fb6f8 
09-02 16:53:18.482: INFO/dalvikvm(4515): Unable to dlopen(/data/data/com.example.hellojni/lib/libSample.so): Cannot find library 
09-02 16:53:18.492: ERROR/Translator(4515): Library /data/data/com.example.hellojni/lib/libSample.so not found 
09-02 16:53:18.492: ERROR/Translator(4515): java.lang.UnsatisfiedLinkError: Library /data/data/com.example.hellojni/lib/libSample.so not found 

Quello che non capisco è che chiaramente esiste la biblioteca, e il sistema operativo sta tentando di caricarlo ... così che cosa avrebbe fatto fallire?

Seguendo il consiglio di uno dei commentatori, ho provato ad allegare tramite strace per ottenere informazioni più dettagliate sull'errore. Il registro può essere trovato come github gist.

L'errore sembra essere sulle linee 47-51:

mprotect(0x4235d000, 4096, PROT_READ) = 0 
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbeb58080) = -1 ENOTTY (Not a typewriter) 
write(1, "bionic/linker/linker.c:1243| ERROR: 34 unknown reloc type 3 @ 0x811a854c (2441)\n", 83) = 83 
write(1, "bionic/linker/linker.c:1641| ERROR: failed to link /data/data/com.example.hellojni/lib/libSample.so\n", 100) = 100 
munmap(0x81000000, 8839168)    = 0 

Ecco il readelf della biblioteca:

arm-eabi-readelf -d libSample.so 

Dynamic section at offset 0x80b648 contains 17 entries: 
    Tag  Type       Name/Value 
0x00000019 (INIT_ARRAY)     0x7ff234 
0x0000001b (INIT_ARRAYSZ)    76 (bytes) 
0x00000004 (HASH)      0xd4 
0x00000005 (STRTAB)      0x7f41c 
0x00000006 (SYMTAB)      0x2650c 
0x0000000a (STRSZ)      1197287 (bytes) 
0x0000000b (SYMENT)      16 (bytes) 
0x00000003 (PLTGOT)      0x80c6f0 
0x00000002 (PLTRELSZ)     76480 (bytes) 
0x00000014 (PLTREL)      REL 
0x00000017 (JMPREL)      0x1ccb84 
0x00000011 (REL)      0x1a3904 
0x00000012 (RELSZ)      168576 (bytes) 
0x00000013 (RELENT)      8 (bytes) 
0x00000016 (TEXTREL)     0x0 
0x6ffffffa (RELCOUNT)     2412 
0x00000000 (NULL)      0x0 
+0

Ho provato sia con loadLibrary e del carico – I82Much

+1

Quale versione di Android stai usando? Le versioni più recenti sono un po 'più prolisse a proposito degli errori dlopen(). Le versioni precedenti del linker dinamico riportavano "non trovato" per tutto. Una cosa che a volte aiuta è mettere insieme un banale programma da riga di comando in C che non fa altro che chiamare dlopen() sulla tua lib e riportare il risultato. Se fallisce, sai che è un problema di lib; se ha successo, il problema è altrove. – fadden

+1

Come si compila un programma del genere con il compilatore incrociato Android? Non so dove trovare i simboli non risolti dlopen, dlerror, ecc braccio-EABI-nm -u libTester.exe U __aeabi_unwind_cpp_pr1 U __gxx_personality_v0 U __sF U dlclose U dlerror U dlopen U dlsym U fprintf – I82Much

risposta

3

Penso che possa essere più probabile che una libreria che il vostro .so dipende da non essere stato trovato Ma questo è solo se i file .so possono essere caricati da una SDCard, in primo luogo.

+0

Come ho detto verso la fine, l'ho inserito nello spazio di archiviazione locale dell'app e ho ottenuto lo stesso errore. Ho avuto problemi con i collegamenti non risolti e ho ricevuto un errore molto diverso (o almeno un testo più informativo) – I82Much

+1

Ti sento, JNI è sempre così divertente –

+0

Grazie - Stavo solo guardando l'errore di run-time e la linea di codice. Risulta che il messaggio di errore effettivo nel debugger indicava una dipendenza che non era in grado di trovare. – Matt

1

Per favore prova a seguire le linee guida che ho fornito per il problema a cui ti riferivi all'inizio della tua domanda (intendo here). In bocca al lupo!

+0

Mi hai dato qualche informazione in più (vale a dire allegare tramite strace). Potresti leggere le informazioni aggiornate che ho dato sul registro strace e vedere se ne sai qualcosa al riguardo? "unknown reloc type 3" – I82Much

+0

Non ho visto questo tipo di errore nelle mie librerie. Dopo alcuni scavi ho trovato che questo reloc tipo 3 è R_ARM_REL32 definito in elf.h. Ho cercato questo su google e questa conversazione è uscita: http://groups.google.com/group/android-ndk/browse_thread/thread/db718cceaded89dc/a601f3ecdcf070a7?#a601f3ecdcf070a7 Si accenna che R_ARM_REL32 non è un trasferimento valido in eseguibili dinamici. Non sono un esperto di C/C++ quindi non posso aiutarti con l'esatta spiegazione, ma forse questo ti dirà di più di quanto mi dice. –

+0

Maciej potrebbe fare qualcosa. Che ne dici di creare una libreria più semplice (una copia rinominata di libhello-jni?) E provare a caricarla tramite lo stesso metodo. Quindi prova a creare versioni ridotte della tua libreria. –

0

Ok, non ho mai usato Android prima, quindi potrebbe essere un commento stupido, ma in JavaSE non funzionerà, perché il file della libreria è "sbagliato". Vedi, tu scrivi un programma in java, quindi non sai in quale SO funzionerà, giusto? Come puoi sapere se la lib che vuoi caricare è nel file myLib.so o myLib.dll o myLib.32TestNotHackerSufix? Beh ... non farlo! È java! Risolverà il suffisso della lib per te in base al tuo SO.

uso Prova

File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample"); 

senza ".so".

(Suppongo che tu non abbia qualcosa come "LIBRARY_PATH" in Android, quindi caricherà la tua lib dal percorso che gli dici ....Se tale cosa esiste in Android si shoul caricare il tuo lib come

System.load("libSampe"); 

e mettere la directory in LIBRARY_PATH prima di iniziare la vostra app)

+1

Grazie, ma non era questo il problema. Se la libreria è stata creata correttamente e in libs/armeabi, verrà copiata sul dispositivo e in un percorso a conoscenza del dispositivo Android. – I82Much

3

Fa libSample.so ha qualunque dipendenze da altri librerie condivise che si può essere Building? Se è così, è necessario System.loadLibrary o System.load le sue dipendenze prima, assicurandosi di caricare le librerie più "di base" prima di altre, come se fossero librerie statiche. Almeno sembra essere così con NDK 7b.

Per esempio, se libSample.so dipende libfoo.so si dovrebbe fare qualcosa di simile:

System.loadLibrary("foo"); 
System.loadLibrary("Sample"); 
+0

come faccio a farlo ..... caricare le dipendenze – mohitum

+0

Ho aggiunto un esempio per il caricamento delle dipendenze a questa risposta. – ldav1s

+0

Funziona per me! Mi chiedo che Nexus abbia accettato qualsiasi ordine di biblioteche, ma Kindle Fire no! – deko

Problemi correlati