¿Cómo comstackr la biblioteca dinámica para una aplicación JNI en Linux?

Estoy usando Ubuntu 10.10

Entonces eso es lo que hice.

Hello.java :

class Hello { public native void sayHello(); static { System.loadLibrary("hellolib"); } public static void main(String[] args){ Hello h = new Hello(); h.sayHello(); } } 

Luego ejecuté los siguientes comandos:

 dierre@cox:~/Scrivania/provajni$ javac Hello.java dierre@cox:~/Scrivania/provajni$ javah -jni Hello 

Hello.class y Hello.h .

Hello.h :

 /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class Hello */ #ifndef _Included_Hello #define _Included_Hello #ifdef __cplusplus extern "C" { #endif /* * Class: Hello * Method: sayHello * Signature: ()V */ JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 

Luego creé Hello.cpp :

 #include  #include "Hello.h" #include  using namespace std; JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) { cout << "Hello World!" << endl; return; } 

Y ahora la parte donde creo que me equivoqué. Me inspiré en esta guía ( comstackr la sección Biblioteca de objetos dynamics o compartidos ) :

 dierre@cox:~/Scrivania/provajni$ gcc -I"/usr/lib/jvm/java-6-sun/include" -I"/usr/lib/jvm/java-6-sun/include/linux" -o hellolib.so -shared -Wl,-soname,hello.so Hello.cpp -static -lc 

que genera el archivo hellolib.so

Pero cuando trato de ejecutarlo con java Hello , tengo este error:

 Exception in thread "main" java.lang.UnsatisfiedLinkError: no hellolib in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1028) at Hello.(Hello.java:4) Could not find the main class: Hello. Program will exit. 

Incluso intenté esto:

  LD_LIBRARY_PATH=`pwd` export LD_LIBRARY_PATH 

sin resultados

Sé que estoy haciendo algo extremadamente estúpido, pero no puedo entender de qué se trata. La lib dinámica se genera con la opción -shared, ¿no es así?

Actualización # 1

Intenté static { System.load("/home/dierre/Scrivania/provajni/hellolib.so"); } static { System.load("/home/dierre/Scrivania/provajni/hellolib.so"); } para ver si eso funcionó pero ahora:

 Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/dierre/Scrivania/provajni/hello.so: /home/dierre/Scrivania/provajni/hello.so: undefined symbol: _ZSt4cout at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699) at java.lang.Runtime.load0(Runtime.java:770) at java.lang.System.load(System.java:1003) at Hello.(Hello.java:4) 

Actualización # 2 Ok, para resolver el problema de Actualización # 1 , tuve que usar g++ insted of gcc , obviamente. Aún tiene problemas para usar el método de load . Parece que no puedo decir el camino correcto.

La biblioteca nativa puede ser cargada por loadLibrary con un nombre válido. Por ejemplo, lib XXXX .so para la familia de Linux, su hellolib.so debe cambiar el nombre a libhello.so. Por cierto, desarrollo java con jni, separaré la implementación y la interfaz nativa (.c o .cpp).

 static { System.loadLibrary("hello"); // will load libhello.so } 

El encabezado de implementación (HelloImpl.h):

 #ifndef _HELLO_IMPL_H #define _HELLO_IMPL_H #ifdef __cplusplus extern "C" { #endif void sayHello (); #ifdef __cplusplus } #endif #endif 

HelloImpl.cpp:

 #include "HelloImpl.h" #include  using namespace std; void sayHello () { cout << "Hello World!" << endl; return; } 

Hola.c (Prefiero comstackr jni en c):

 #include  #include "Hello.h" #include "HelloImpl.h" JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) { sayHello(); return; } 

Finalmente, podemos comstackrlos en algunos pasos:

  1. comstackr obj (generar HelloImpl.o)

g ++ -c -I "/ opt / java / include" -I "/ opt / java / include / linux" HelloImpl.cpp

  1. comstackr jni con .o

g ++ -I "/ opt / java / include" -I "/ opt / java / include / linux" -o libhello.so -shared -Wl, -soname, hello.so Hello.c HelloImpl.o -static -lc

en el paso 2, usamos g ++ para comstackrlo. Esto es muy importante. y puedes ver Cómo mezclar C y C ++

Después de la comstackción, puede verificar la función nombrando con nm:

 $ nm libhello.so |grep say 00000708 T Java_Hello_sayHello 00000784 t _GLOBAL__I_sayHello 00000718 T sayHello 

Hay un Java_Hello_sayHello marcado con T. Debe ser exactamente igual al nombre de su método nativo. Si todo esta bien. puedes ejecutarlo:

 $ java -Djava.library.path=. Hello Hello World! 

Finalmente mi código funciona. Esto es hello.java

 public class hello { public native void sayHello(int length) ; public static void main (String args[]) { String str = "I am a good boy" ; hello h = new hello () ; h.sayHello (str.length() ) ; } static { System.loadLibrary ( "hello" ) ; } } 

Debe comstackrlo como:

 $ javac hello.java 

Para crear el archivo .h, debe ejecutar este comando:

 $ javah -jni hello 

Esto es hello.h :

 JNIEXPORT void JNICALL Java_hello_sayHello (JNIEnv *, jobject, jint); 

Aquí está hello.c :

 #include #include #include "hello.h" JNIEXPORT void JNICALL Java_hello_sayHello (JNIEnv *env, jobject object, jint len) { printf ( "\nLength is %d", len ); } 

Para comstackr esto y crear una biblioteca compartida, debemos ejecutar este comando:

 $ gcc -I/usr/lib/jvm/java-6-openjdk/include -o libhello.so -shared hello.c 

Entonces, finalmente ejecuta este:

 $ java -Djava.library.path=. hello 

Esto se queja de que los símbolos de C ++ no están disponibles. Me parece recordar, cuando solía hacer cosas JNI todo el tiempo que había problemas de vinculación en las bibliotecas C ++ y siempre nos apegamos a la simple C

Si cambia su código para que sea estándar C (y cambie el nombre del archivo):

 #include  #include "Hello.h" #include  JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) { printf("Hello World"); return; } 

Y comstackrlo

 gcc -I/usr/lib/jvm/java-6-openjdk/include -o libhellolib.so -shared Hello.c 

Funciona

 java -Djava.library.path=`pwd` Hello Hello World