Erro de link JNI Hello World Unsatisfied

Esta é minha primeira tentativa no JNI. Meu objective final é obter todas as tarefas atualmente em execução em uma máquina, mas preciso obter um exemplo simples em execução. Eu continuo recebendo este erro quando tento executar o meu programa principal. Eu forneci meu programa principal Java simples, o arquivo de header gerado e o erro.

Eu não sei o que esta DLL poderia ser dependente. Foi inicialmente referenciando uma DLL que eu rastreei e coloquei em system32 (msvcr90.dll).

Aqui está o comando que eu usei para compilar o código C também que produziu os arquivos DLL, OBJ, LIB, EXP e manifesto.

cl -I “C: \ Arquivos de programas \ Java \ jdk1.6.0 \ include” -I “C: \ Arquivos de programas \ Java \ jdk1.6.0 \ include \ win32” -MD -LD HelloWorld.c -FeHelloWorld.dll

class HelloWorld { private native void print(); public static void main(String[] args) { new HelloWorld().print(); } static { System.load("C:\\temp\\HelloWorld.dll"); } } #include  #include  #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) { printf("Hello World!\n"); return; } /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: print * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif java.lang.UnsatisfiedLinkError: C:\temp\HelloWorld.dll: A dynamic link library (DLL) initialization routine failed at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(Unknown Source) at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.load0(Unknown Source) at java.lang.System.load(Unknown Source) at HelloWorld.(HelloWorld.java:7) Exception in thread "main" 

O erro de link insatisfeito pode significar que muitas coisas deram errado. eu usaria

 System.loadLibrary("HelloWorld"); 

Ao invés de

 System.load(); 

Como TwentyMiles sugeriu.

Além disso, ao invocar seu programa, você precisa (supondo que sua DLL esteja no mesmo diretório que seus arquivos de class:

java -Djava.library.path =. Olá Mundo

Aqui está uma demo simples que eu fiz que chama uma function de API do Win32 (MessageBox)

Classe Java

 class CallApi{ private native String showMessageBox(String msg); private native double getRandomDouble(); static{ try{ System.loadLibrary("CallApi"); System.out.println("Loaded CallApi"); }catch(UnsatisfiedLinkError e){ //nothing to do System.out.println("Couldn't load CallApi"); System.out.println(e.getMessage()); } } public static void main(String args[]){ CallApi api = new CallApi(); double randomNumber = api.getRandomDouble(); String retval = api.showMessageBox("Hello from Java!\n"+ "The native random number: "+randomNumber); System.out.println("The native string: "+retval); } } 

Arquivo de header gerado

 /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class CallApi */ #ifndef _Included_CallApi #define _Included_CallApi #ifdef __cplusplus extern "C" { #endif /* * Class: CallApi * Method: showMessageBox * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox (JNIEnv *, jobject, jstring); /* * Class: CallApi * Method: getRandomDouble * Signature: ()D */ JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 

O código da DLL C

 #include "CallApi.h" #include  #include  #include  #pragma comment(lib,"user32.lib") JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox (JNIEnv *env, jobject thisObject, jstring js) { //first convert jstring to const char for use in MessageBox const jbyte* argvv = (*env)->GetStringUTFChars(env, js, NULL); char* argv =(char *) argvv; //Call MessageBoxA MessageBox(NULL, argv, "Called from Java!", MB_ICONEXCLAMATION | MB_OK); return js; } JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble (JNIEnv *env, jobject thisObject) { double num1; srand((unsigned)(time(0))); num1 = ((double)rand()/(double)RAND_MAX); return num1; } 

Instruções de compilation

Eu compilar com o Visual C ++ express 2008 cl, removendo o sinalizador -ML, uma vez que causa uma exceção quando o código Java tenta chamar o código nativo:

cl / I “c: \ Arquivos de programas \ Java \ jdk1.6.0_10 \ include” / I “c: \ Arquivos de programas \ Java \ jdk1.6.0_10 \ incluem \ win32” -LD CallApi.c -FeCallApi.dll

Então, para executar o código:

java -Djava.library.path =. CallApi

Eu não estou afirmando entender a situação o suficiente para explicá-lo, no entanto, alguns usuários relataram o erro ao usar o sinalizador de compilador “-MD”.

Para mais informações, consulte Java Native Interface (JNI) – Impossível usar o VS2005 com Java? que discute esse problema e oferece soluções possíveis, e pense no blog de tecnologia para alternativas.

Eu acredito que você deveria estar usando

 System.loadLibrary("HelloWorld"); 

em vez de System.load. A LoadLibrary verificará o caminho do seu sistema (não o caminho da biblioteca Java), portanto, certifique-se de que o HelloWorld.dll esteja em um diretório onde possa ser encontrado. Observe também que ele não exige o caminho completo e você não precisa adicionar a extensão dll ao final.

Acabei de remover a opção -MD e compilado funcionou como charme

 cl -I"C:\Program Files\Java\jdk1.6.0_21\include" -I"C:\Program Files\Java\jdk1.6.0_21\include\win32" -LD HelloWorld.c -FeHelloWorld.dll