2010-09-02 4 views
15

J'ai un problème similaire à this question, mais légèrement différent. J'ai compilé une bibliothèque .so à utiliser avec JNI. Parce qu'il est grand (15 Mo), je le place sur la carte SD au lieu de l'utiliser dans l'application standard.Android - échec lors du chargement de la bibliothèque

Le fichier est appelé libSample.so et il est situé à /data/library/libSample.so

je charge dans un bloc d'initialisation statique:

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()); 
    } 

est ici la sortie logcat pertinente:

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 

Tous idée quel est le problème? J'ai lu le post à propos de can android load dll's from sdcard in native mode qui disait que la carte SD ne peut pas être utilisée pour charger les bibliothèques, alors j'ai déplacé le .so dans /data/data/com.example.hellojni/lib/libSample.so (les données de l'application privée emplacement de stockage). Aucun changement:

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 

Ce que je ne comprends pas que la bibliothèque existe bien, et le système d'exploitation tente de le charger ... donc ce qui en ferait échouer? Suite à l'avis de l'un des commentateurs, j'ai essayé d'attacher via strace pour obtenir des informations d'erreur plus détaillées. Le journal peut être trouvé comme github gist.

L'erreur semble être sur les lignes 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 

Voici le readelf de la bibliothèque:

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

J'ai essayé à la fois avec loadLibrary et charge – I82Much

+1

Quelle version d'Android que vous utilisez? Les versions plus récentes sont un peu plus détaillées sur les échecs dlopen(). Les anciennes versions de l'éditeur de liens dynamiques ont indiqué "non trouvé" pour tout. Une chose qui aide parfois est de mettre en place un programme de ligne de commande trivial en C qui ne fait qu'appeler dlopen() sur votre lib et rendre compte du résultat. Si cela échoue, vous savez que c'est un problème de lib. s'il réussit, le problème est ailleurs. – fadden

+1

Comment compilez-vous un tel programme avec le compilateur croisé android? Je ne sais pas où trouver les symboles non résolus dlopen, dlerror, etc. bras 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

Répondre

3

Je pense qu'il est plus probable qu'une bibliothèque que votre .donc dépend de ne pas être trouvé. Mais ce n'est que si les fichiers .so peuvent être chargés à partir d'une carte SD en premier lieu.

+0

Comme je l'ai mentionné vers la fin, je l'ai placé dans l'espace de stockage local de l'application et j'ai eu la même erreur. J'ai eu des problèmes avec des liens non résolus avant et j'ai eu une erreur très différente (ou au moins, un texte plus informatif) – I82Much

+1

Je vous entends, JNI est toujours tellement amusant –

+0

Merci - Je regardais seulement l'erreur d'exécution et la ligne de code. Il s'avère que le message d'erreur réel dans le débogueur a indiqué une dépendance qu'il n'a pas pu trouver. – Matt

1

Veuillez suivre les directives que j'ai fournies pour le problème auquel vous faisiez référence au début de votre question (je veux dire here). Bonne chance!

+0

Vous m'avez donné plus d'informations (à savoir attacher via strace). Pourriez-vous s'il vous plait lire les informations mises à jour que j'ai données sur le journal strace et voir si vous en savez quelque chose? "unknown reloc type 3" – I82Much

+0

Je n'ai pas vu ce genre d'erreur dans mes bibliothèques. Après quelques recherches, j'ai trouvé que ce type de relocalisation 3 est R_ARM_REL32 défini dans elf.h. J'ai cherché à ce sujet dans google et cette conversation est sorti: http://groups.google.com/group/android-ndk/browse_thread/thread/db718cceaded89dc/a601f3ecdcf070a7?#a601f3ecdcf070a7 Il mentionne que R_ARM_REL32 n'est pas une relocalisation valide dans exécutables dynamiques. Je ne suis pas un expert C/C++ donc je ne peux pas vous aider avec l'explication exacte, mais peut-être que cela vous en dira plus alors il me le dit. –

+0

Maciej peut être sur quelque chose. Pourquoi ne pas créer une bibliothèque plus simple (une copie renommée de libhello-jni?) Et essayer de la charger par la même méthode. Ensuite, essayez de réduire les versions de votre bibliothèque. –

0

Ok, je n'ai jamais utilisé Android auparavant, donc c'est peut-être un commentaire stupide, mais dans JavaSE ça ne marchera pas trop, parce que votre fichier de bibliothèque est "faux". Vous voyez, vous écrivez un programme en Java, donc vous ne savez pas dans quoi il va fonctionner, non? Comment pouvez-vous savoir si la bibliothèque que vous voulez charger se trouve dans le fichier myLib.so ou myLib.dll ou myLib.32TestNotHackerSufix? Eh bien ... vous ne faites pas! C'est java! Il va résoudre le suffixe de la lib pour vous en fonction de votre SO.

Essayez utilisation

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

sans ".so".

(Je suppose que vous n'avez pas quelque chose comme "LIBRARY_PATH" dans Android, donc il va charger votre lib du chemin que vous lui dites ....Si une telle chose existe dans Android, vous shoul charger votre lib comme

System.load("libSampe"); 

et mettez votre répertoire LIBRARY_PATH avant de commencer votre application)

+1

Merci, mais ce n'était pas le problème. Si la bibliothèque est correctement construite, et dans libs/armeabi, elle sera copiée sur l'appareil et dans un chemin connu de l'appareil Android. – I82Much

3

Est-ce que libSample.so ont des dépendances sur d'autres bibliothèques partagées que vous pouvez construire? Si oui, vous devrez System.loadLibrary ou System.load ses dépendances d'abord, en veillant à charger les bibliothèques les plus «basiques» avant les autres, comme s'il s'agissait de bibliothèques statiques. Au moins, il semble que ce soit ainsi avec NDK 7b.

Par exemple, si libSample.so dépend de libfoo.so que vous devriez faire quelque chose comme:

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

comment puis-je faire ..... charger des dépendances – mohitum

+0

J'ai ajouté un exemple pour le chargement des dépendances à cette réponse. – ldav1s

+0

Fonctionne pour moi! Je me demande si Nexus a accepté n'importe quel ordre de bibliothèques, mais pas Kindle Fire! – deko

Questions connexes