quinta-feira, 22 de julho de 2010

Embutindo Java em uma aplicação C

Vamos descrever como embutir a máquina virtual do Java (JVM) em uma simples aplicação C, para isso, estamos usando o IDE Eclipse Ganymede (versão 3.4) sobre o Linux Ubuntu 10.04.

1 - Crie um projeto C no eclipse, conforme mostram as figuras abaixo:





Depois da criação do projeto C, precisamos configurar os includes (cabeçalhos) e as bibliotecas da API C do JDK (Kit de desenvolvimento Java), veja nas figuras a seguir:




Agora, vamos criar o arquivo com a extensão ".c" que criará a JVM e também executaremos uma chamada a uma classe de exemplo que definiremos mais adiante.

Veja o arquivo EmbedJVM.c

-------------------------------------------------------------------------
/*
============================================================================
Name : EmbedJVM.c
Author : user
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/

#include
#include
#include
#define PATH_SEPARATOR ':' /* define it to be ':' on Solaris */
#define USER_CLASSPATH ".:/home/user/workspace/JNITestProject/bin" /* where Prog.class is */

int main(void) {
JNIEnv *env;
JavaVM *jvm;
jint res;
jclass cls;
jmethodID mid;
jstring jstr;
jclass stringClass;
jobjectArray args;

JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=" USER_CLASSPATH;
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);


if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
}

cls = (*env)->FindClass(env, "Prog");

if (cls == NULL) {
exit(1);
}

mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
if (mid == NULL) {
exit(1);
}

jstr = (*env)->NewStringUTF(env, " from C!");
if (jstr == NULL) {
exit(1);
}

stringClass = (*env)->FindClass(env, "java/lang/String");
args = (*env)->NewObjectArray(env, 1, stringClass, jstr);
if (args == NULL) {
exit(1);
}

(*env)->CallStaticVoidMethod(env, cls, mid, args);

if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}

(*jvm)->DestroyJavaVM(jvm);


return 0;
}

-------------------------------------------------------------------------

Esse arquivo deve ser colocado dentro da pasta "src" do projeto C criado anteriormente.
Note que, nesse arquivo o classpath se referencia ao seguinte diretório:

#define USER_CLASSPATH ".:/home/user/workspace/JNITestProject/bin"

Esse projeto "JNITestProject" é um projeto Java na qual criamos uma classe com o nome de "Prog", conforme abaixo:

-------------------------------------------------------------------------
public class Prog {

/**
* @param args
*/
public static void main(String[] args) {
String arg = "";

if(args.length >0) {
arg = args[0];
}

System.out.println("Hello World JNI!!! " + arg);
}
}

-------------------------------------------------------------------------

Coloque o arquivo Prog.java dentro do diretório "src" do projeto Java JNITestProject.

Se certifique que o diretório #define USER_CLASSPATH ".:/home/user/workspace/JNITestProject/bin"
existe de fato e que a mesma possui os arquivos compilados (com a extensão ".class") da classe Prog.

O arquivo ".class" da classe Prog deve existir e a variável USER_CLASSPATH configurada corretamente, podemos prosseguir na compilação do projeto C como mostra a seguir:

-------------------------------------------------------------------------------------------
**** Build of configuration Debug for project EmbedJVM ****

make all
Building file: ../src/EmbedJVM.c
Invoking: GCC C Compiler
gcc -I/usr/local/jdk1.6.0_14/include -I/usr/local/jdk1.6.0_14/include/linux -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/EmbedJVM.d" -MT"src/EmbedJVM.d" -o"src/EmbedJVM.o" "../src/EmbedJVM.c"
Finished building: ../src/EmbedJVM.c

Building target: EmbedJVM
Invoking: GCC C Linker
gcc ./src/EmbedJVM.o -ljava -L/usr/local/jdk1.6.0_14/jre/lib/i386 -o"EmbedJVM"
Finished building target: EmbedJVM
-------------------------------------------------------------------------------------------

Com o projeto C compilado, executamos o projeto C e o resultado deverá ser o seguinte:

-------------------------------------------------------------------------------------------

Hello World JNI!!! from C!

-------------------------------------------------------------------------------------------

Assim, conseguimos embutir a JVM numa aplicação C e com isso, abre horizontes para usos da JVM embutida em diversas aplicações, como em sistemas embarcados, etc.

Referências:

http://java.sun.com/docs/books/jni/

http://en.wikipedia.org/wiki/Java_Native_Interface
http://javafree.uol.com.br/topic-13913-JNI-Java-Native-Interface.html

Nenhum comentário:

Postar um comentário