Bom dia pessoal. Eu tô precisando de um tutorial de JNI, pode ser um e-book, artigo acadêmico ou afins. Antes que alguém pergunte, aqui na empresa tem um proxy e eu não posso fazer downloads, logo, a busca no Google não adianta nada nesse caso.
Se alguém puder enviar por email pra mim, agradeço.
Ajuda com o Hello World do JNI [Resolvido]
14 Respostas
Bacana, baixei as apostilas e tal, mas fui fazer o meu Hello World! e deu pau.
Gostaria de saber se alguém pode me ajudar, já que estou aprendendo o JNI agora.
Passo a passo vou descrever e mostrar o que fiz.
1 - Código em java
class HelloWorld {
private native void print();
public static void main(String[] args) {
new HelloWorld().print();
}
static {
System.loadLibrary("HelloWorld");
}
}
2 - Gerei o .class
javac HelloWorld
3 - Gerei o .h
javah -jni HelloWorld.class
4 - Editei meu arquivo em C
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
Daí digitei no meu terminal do Linux, para gerar o .so:
cc -G -I/opt/jdk1.6.0_1/include -I/opt/jdk1.6.0_1/include/linux HelloWorld.c -o libHelloWorld.so
Daí recebi a seguinte mensagem de erro:
HelloWorld.c:1:17: error: jni.h: Arquivo ou diretório inexistente
In file included from HelloWorld.c:3:
HelloWorld.h:15: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?void?
HelloWorld.c:5: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?void?
Eu gerei um .so pq estou no Linux. Parece que está dando pau no Import do jni, no meu arquivo em C. Alguém tem alguma idéia do que está acontecendo?
Hum… você tem um arquivo jni.h nesses diretórios especificados com -I ? tem certeza que é /opt/jdk1.6.0_1 não /opt/jdk1.6.0_01 ?
Thingol, tentei aqui trocar de 1 para 01 no final, mas continua a mesma coisa viu. O que eu fiquei pensando é o seguinte: no Windows, as dll fican na Win32, mas onde será que ficam os arquivos de extensão .so, no Linux? Talvez esse seja o principal problema, pq realmente ele não encontra o jni.
Primeiro resolva o erro de compilação, que diz claramente que o compilador não conseguiu achar o arquivo jni.h nos diretórios especificados com a opção -I. O arquivo jni.h é necessário para poder definir algumas coisas usadas por HelloWorld.h, portanto você não pode omiti-lo.
Eu vou dar um
find / -name jni.h
no Linux, daí ele vai me dizer onde está esse arquivo. Se eu não conseguir, eu volto aqui e a gente vê o que faz.
Thingol, o comando retornou o caminho completo para o arquivo:
/opt/jdk1.6.0_11/include/jni.h
era o JDK 6 Update 11, e não o 01, como eu havia digitado.
Agora eu digito o seguinte:
cc -G -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux HelloWorld.c -o libHelloWorld.so
Mas ele retorna o seguinte erro:
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
O que pode ser agora? Eu vou dando uma olhada no código enquanto isso.
Para compilar um .so os parâmetros não são suficientes. Você usou apenas -o arquivo.so; isso faz com que o linker tente achar um “main”, o que obviamente não é o que você quer.
O comando, aparentemente, é o que você pode achar nesta página:
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html
# obviamente o comando a seguir é todo em uma linha
gcc -o libnativelib.so -shared -Wl,-soname,libnative.so
-I/export/home/jdk1.2/include
-I/export/home/jdk1.2/include/linux nativelib.c
-static -lc
(Não sabia que existia esse treinamento da Sun. Olhe os outros capítulos.)
Tentei da maneira abaixo:
gcc -o libHelloWorld.so -shared -Wl, -HelloWorld, libHelloWorld.so -I/export/opt/jdk1.6.0_11/include -I/export/opt/jdk1.6.0_11/include/linux HelloWorld.so
Mas recebi a msgm:
gcc: libHelloWorld.so: Arquivo ou diretório inexistente
gcc: HelloWorld.so: Arquivo ou diretório inexistente
gcc: unrecognized option '-HelloWorld.so,'
Hum hum hum… você viu que o Linux tem também seus segredos. No seu caso, você pôs espaços depois de cada vírgula; não é para pô-los. O comando é realmente “-Wl,-soname,libSeuArquivo.so”, sem os espaços. “man gcc” para as opções.
Então cara, digitei assim:
gcc -o libHelloWorld.so -shared -Wl,-HelloWorld,libHelloWorld.so -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux HelloWorld.c -static -lc
E agora obtive:
/usr/bin/ld: unrecognized option '-HelloWorld'
/usr/bin/ld: use the --help option for usage information
collect2: ld returned 1 exit status
Use o “man gcc” ou “man ld”, não sei qual deles tem a opção “-soname”.
A opção tem o nome de “-soname” mesmo; não é algo que você tem de substituir pelo nome do seu arquivo .so.
Bom, onde tinha -HelloWorld, eu troquei para -soname. Agora parece que deu certo.
Ficou assim
gcc -o libHelloWorld.so -shared -Wl,-soname,libHelloWorld.so -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux
Funciounou! 
Thingol,obrigado pela paciência e disposição. Mais uma vez, muitíssimo obrigado. Bom trabalho pra você. Vlw!