Bonjour,

Je souhaite écrire un HelloWorld pour JNI, mais celui-ci ne fonctionne pas.

Voici l'arborescence de mon projet :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
.
+-- bin
|   `-- test
|       `-- TestJNI.class
+-- native
|   +-- testjni.so
|   +-- test_TestJNI.c
|   +-- test_TestJNI.h
|   `-- test_TestJNI.o
`-- src
    `-- test
        `-- TestJNI.java
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cat src/test/TestJNI.java 
package test;
 
public class TestJNI {
 
	static {
		System.loadLibrary("testjni");
	}
 
	public static native void helloWorld();
 
	public static void main(String... args) {
		helloWorld();
	}
 
}
J'ai généré test_TestJNI.h grâce à la commande suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
javah -classpath bin -d native test.TestJNI
J'ai écrit mon fichier .c :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
$ cat native/test_TestJNI.c
#include <jni.h>
#include <stdio.h>
#include "test_TestJNI.h"
 
JNIEXPORT void JNICALL Java_test_TestJNI_helloWorld(JNIEnv * env, jclass class) {
	printf("Hello world !\n");
}
J'ai ensuite généré mon .so :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
$ cd native
$ gcc -fPIC -c test_TestJNI.c -o test_TestJNI.o -I/usr/lib/jvm/java-6-openjdk-amd64/include
$ gcc -shared -o testjni.so test_TestJNI.o
$ cd ..
J'ai besoin de -fPIC car mon système est une 64bits, sans quoi j'ai l'erreur suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
Donc à partir de là j'ai mon .so.

Je tente ensuite d'exécuter :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
$ java -Djava.library.path=native -cp bin test.TestJNI
Exception in thread "main" java.lang.UnsatisfiedLinkError: no testjni in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1681)
	at java.lang.Runtime.loadLibrary0(Runtime.java:840)
	at java.lang.System.loadLibrary(System.java:1047)
	at test.TestJNI.<clinit>(TestJNI.java:6)
Même problème avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
$ java -Djava.library.path="$PWD/native"
(ou si je déplace mon .so à la racine du projet et que j'utilise -Djava.library.path=.)

Si je remplace dans TestJNI.java la ligne :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
System.loadLibrary("testjni");
par :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
System.load("/home/rom/java/TestJNI/native/testjni.so");
alors ça fonctionne.

Qu'ai-je mal fait ?

Merci de votre aide.