2015-09-24 2 views
2

Je suis en train de travailler construire ma première application JNI, suivant ce tutoriel: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.htmlJNI UnsatisfiedLinkError sans mauvais noms de méthode et avec le chemin de la bibliothèque spécifiée

Problème: Pendant l'exécution de mon application, je reçois un java.lang Erreur .UnsatisfiedLinkError.

D'abord, j'écrit la classe HelloJNI.java:

public class HelloJNI { 
    static { 
     System.loadLibrary("hello"); // Load native library at runtime 
            // hello.dll (Windows) or libhello.so (Unixes) 
    } 

    // Declare a native method sayHello() that receives nothing and returns void 
    private native void sayHello(); 

    // Test Driver 
    public static void main(String[] args) { 
     new HelloJNI().sayHello(); // invoke the native method 
    } 
} 

Cette classe I compilé avec: javac HelloJNI.java Ensuite, je courais javah HelloJNI Ce produit le fichier suivant HelloJNI.h:

/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class HelloJNI */ 

#ifndef _Included_HelloJNI 
#define _Included_HelloJNI 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  HelloJNI 
* Method: sayHello 
* Signature:()V 
*/ 
JNIEXPORT void JNICALL Java_HelloJNI_sayHello 
    (JNIEnv *, jobject); 

#ifdef __cplusplus 
} 
#endif 
#endif 

Ensuite, je mis en œuvre HelloJNI.c:

#include <jni.h> 
#include <stdio.h> 
#include "HelloJNI.h" 

// Implementation of native method sayHello() of HelloJNI class 
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) { 
    printf("Hello World!\n"); 
    return; 
} 

Enfin, je compilé la classe c:

  • -I gcc "/ usr/lib/jvm/java-8-oracle/include" -I "/ usr/lib/jvm/java-8-oracle/include/linux" -c -Wall -Werror -fpic HelloJNI.c
  • gcc -o -shared hello.so HelloJNI.o

Cela produit t Il dépose hello.so et HelloJNI.o. Ensuite, j'essaie d'exécuter le code:

  • java -Djava.library.path =. HelloJNI Cela produit l'erreur:

    Exception dans le thread "principal" java.lang.UnsatisfiedLinkError: pas bonjour dans java.library.path à java.lang.ClassLoader.loadLibrary (ClassLoader.java:1864) à java .lang.Runtime.loadLibrary0 (Runtime.java:870) à java.lang.System.loadLibrary (System.java:1122) à HelloJNI. (HelloJNI.java:3)

Cela semble être l'erreur JNI la plus commune sur Internet ... Mes noms de méthodes semblent être corrects. J'ai également couru:

  • nm hello.so | grep dire

Cela me donne: 00000000000006b0 T Java_HelloJNI_sayHello qui semble être correcte, à savoir le compilateur n'a pas ajouté des caractères supplémentaires. J'ai simplement manqué d'idées de choses que je pourrais essayer. Aucune suggestion?

Mon OS: Linux Mint 13, version de GCC 4.7.3, version java 1.8.0_60

UPDATE ========== ============= == Lorsque je remplace System.loadLibrary("hello"); par System.load("/usr0/home/jkinable/workspace/javaIDEA/jnitest/hello.so"); mon exemple HelloWorld fonctionne! Cependant, je ne veux pas utiliser un chemin absolu, donc je cherche toujours un moyen d'utiliser System.loadLibrary("hello"); à la place? Aucune suggestion?J'ai également essayé d'utiliser un autre système Linux, mais j'ai le même problème.

+0

Selon le message d'erreur, il semble que le problème n'est pas que la fonction ne peut pas être trouvée, mais plutôt que la bibliothèque entière est introuvable. – Michael

+0

Probablement vous avez raison (voir mise à jour). Vous ne savez pas comment résoudre ce problème :( –

Répondre

3

Il s'avère que le problème est dû à une convention de nommage sur les plateformes unix/linux! Lors de l'utilisation: System.loadLibrary ("hello"); le fichier ne doit pas être nommé hello.so! Au lieu de cela, le nom doit être libhello.so. Sous Windows, utilisez hello.dll. Je suis surpris que ce problème ne soit pas mentionné dans le tutoriel JNI d'IBM: http://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html

Je ne suis pas sûr de la rationalité derrière ce problème. Pourquoi chargeriez-vous une bibliothèque "hello" qui devrait s'appeler libhello.so sur votre système de fichiers (au lieu de hello.so)?

+2

Le préfixe "lib" pour les bibliothèques est standard pour les systèmes d'exploitation Linux (voir par exemple http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html). Chaque bibliothèque partagée a un nom spécial appelé "soname" Le soname a le préfixe "lib", le nom de la bibliothèque, [suivi par] l'expression ".so ''" _ – Michael

+0

Merci, bonne référence! Je suis d'accord avec les «conventions» Je ne m'attendais pas à ce que ce soit une exigence pour réellement faire fonctionner les choses ... –