I want to create a simple JNI layer. I used Visual studio 2008 to create a dll (Win 32 Console Application project type with DLL as the option). Im getting this exception when I invoke the native method:
Exception occurred during event dispatching:
java.lang.UnsatisfiedLinkError: com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSch
edulerNative.Hello()V
at com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSchedulerNative.Hello(Na
tive Method)
at com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSchedulerUtil.isTaskExis
ts(vcdbaTaskSchedulerUtil.java:118)
at com.tpd.vcdba.console.Dialogs.schedulerWizardPage.scheduleTaskPage.wz
Finish(scheduleTaskPage.java:969)
at com.tpd.vcdba.console.wizard.vcdbaWizard.gotoFinish(vcdbaWizard.java:
434)
at com.tpd.vcdba.console.wizard.wzActionPanel.actionPerformed(wzActionPa
nel.java:163)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
The header file generated is :
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative */
#ifndef _Included_com_tpd_vcdba_console_TaskScheduler_
vcdbaTaskSchedulerNative
#define _Included_com_tpd_vcdba_console_TaskScheduler_
vcdbaTaskSchedulerNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative
* Method: Hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative_Hello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
The implementation file is:
#pragma once
#include "com_tpd_vcdba_console_TaskScheduler_
vcdbaTaskSchedulerNative.h"
#include "stdafx.h"
#include "jni.h"
/*
* Class: com_tpd_vcdba_console_TaskScheduler_vcdbaTaskScheduler_native
* Method: Hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative_Hello
(JNIEnv *envs, jobject obj){
printf("hello world");
}
The java file is:
package com.tpd.vcdba.console.TaskScheduler;
import com.tpd.vcdba.console.TaskScheduler.ScheduleTask;
public class vcdbaTaskSchedulerNative {
public native void Hello();
private static vcdbaTaskSchedulerNative instance = null;
static{
try{
System.loadLibrary("JNITrial");
}
catch(Exception ex){
}
}
public vcdbaTaskSchedulerNative(){
}
public static vcdbaTaskSchedulerNative getInstance(){
if(instance == null){
instance = new vcdbaTaskSchedulerNative();
}
return instance;
}
}
When I invoke the native method "Hello" i get the execption.
Another thing I observed is that when I compile in command line using:
“cl -I"C:\Program Files (x86)\Java\jdk1.7.0\include" -I"C:\Program Files (x86)\Java\jdk1.7.0\include\win32" -LD "C:\Users\administrator.RMDOM\Documents\Visual Studio 2008\Projects\JNITrial\JNITrial\JNIInt.cpp" -FeJNITrial.dll” ,
everything works fine.
Am I missing out something in Visual Studio Settings? I have option Use of MFC as "Use MFC in a Shared DLL", Code generation option as "Multi-threaded DLL (/MD)". Its a 64 bit dll.
Is there something else that I need to add?
Any help is welcome.
Thanks in advance.
Could you tell me what kind of JVM are you using, 32 or 64-bit? Your library is 640bit dll, but in your path I can see C:\Program Files (x86)... so maybe this is the problem.
I figured out the solution.
My project had use precompiled headers option set, so the compiler was skipping the statement:
#include "com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative.h"
Once I removed that option it worked like magic.
Related
This is my first attempt at JNI. My ultimate goal is to get all tasks currently running on a machine, but need to get even a simple example running. I keep getting this error when I try to execute my main program. I have supplied my simple Java main program, the header file generated, and the error.
I do not know what this DLL could be dependent on. It was initially referencing a DLL I tracked down and placed into system32 (msvcr90.dll).
Here is the command I used to compile the C code as well which produced the DLL, OBJ, LIB, EXP and manifest files.
cl -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\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 <jni.h>
#include <stdio.h>
#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 <jni.h>
/* 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.<clinit>(HelloWorld.java:7)
Exception in thread "main"
The Unsatisfied Link Error can mean many things went wrong. I would use
System.loadLibrary("HelloWorld");
Instead of
System.load();
As TwentyMiles suggested.
Also, when invoking your program you need to (assuming your DLL is on the same directory as your class files:
java -Djava.library.path=. HelloWorld
Here's a simple demo I made that calls a Win32 API function (MessageBox)
Java class
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);
}
}
Generated header file
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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
The C DLL code
#include "CallApi.h"
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#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;
}
Compile instructions
I compile with the Visual C++ express 2008 cl, removing the -ML flag since it causes an exception when the Java code tries to call the native code:
cl /I"c:\Program Files\Java\jdk1.6.0_10\include" /I"c:\Program Files\Java\jdk1.6.0_10\include\win32" -LD CallApi.c -FeCallApi.dll
Then, to run the code:
java -Djava.library.path=. CallApi
I'm not claiming to understand the situation enough to explain it, however some users reported the error when using the "-MD" compiler flag.
For more information see Java Native Interface (JNI) - Impossible to use VS2005 with Java? which discusses this problem and offers possible work-arounds and think techie blog for alternatives.
I believe that you should be using
System.loadLibrary("HelloWorld");
instead of System.load. LoadLibrary will check your system path (not the Java library path) so make sure that HelloWorld.dll is in a directory where it can found. Also note that it does not require the full path, and you don't need to add the dll extension to the end.
I just removed -MD option and compiled it worked like charm
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
If you change the location (package) of your native function declaration from the java side without updating the h file, and the signature of the method in the c++ side, It won't resolve to the method and will throw unsatisfied..
package x;
public class A {
private native void print();
...
}
moved to:
package x.y;
public class A {
private native void print();
...
}
This will require regeneration of the H file (to something like Java_x_y_A_print ).
Note you can change those signatures manually but I won't recommend
So I'm new to JNI and I'm following a simple hello word example but I keep getting error UnsatisfiedLinkError. What am I doing wrong? Here's my .h file:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNITEST_jnihellonative */
#ifndef _Included_JNITEST_jnihellonative
#define _Included_JNITEST_jnihellonative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNITEST_jnihellonative
* Method: hellofromc
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNITEST_jnihellonative_hellofromc(JNIEnv *,jobject);
#ifdef __cplusplus
}
#endif
#endif
.c File
#include <jni.h>
#include<stdio.h>
#include<windows.h>
#include "jnihellonative.h"
JNIEXPORT void JNICALL
Java_JNITESTS_jnihellonative_hellofromc(JNIEnv *env, jobject obj){
printf("Hello World");
return;
}
java main class
package JNITEST;
public class Jnihello {
public static void main(String[] args) {
jnihellonative jniprint = new jnihellonative();
jniprint.hellofromc();
}
}
java class
package JNITEST;
public class jnihellonative {
public native void hellofromc();
static{
System.load("C:\\Users\\Kevin\\Documents\\NetBeansProjects\\JniHelloTest.dll");
}
}
I keep getting this error
Exception in thread "main" java.lang.UnsatisfiedLinkError: JNITEST.jnihellonative.hellofromc()V
at JNITEST.jnihellonative.hellofromc(Native Method)
at JNITEST.Jnihello.main(Jnihello.java:19)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)
I have tried using System.load() and System.loadLibrary() but i get same error.
You've changed the name of your class since you generated the .h file and wrote the .c file. The .h file has jnihellonative, your Java code has Jnihello.
I have tried using System.load() and System.loadLibrary()
Irrelevant. You're not getting the exception from either of these, you're getting it when calling your native method.
I'm playing around with JNI on Windows 7x64, Java version is 1.7.0_40 and MinGW / GCC / G++ 4.7.2.
Trying to power off my monitor from Java. So, I've created a class:
public class MonitorTrigger {
static {
try {
System.load(new ClassPathResource("MonitorTrigger.dll").getFile().getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
public native void on();
public native void off();
}
Then, generated h file from it (with Eclipse, but I beleive it uses javah):
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger */
#ifndef _Included_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger
#define _Included_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger
* Method: on
* Signature: ()V
*/
JNIEXPORT void
JNICALL Java_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger_on(
JNIEnv *, jobject);
/*
* Class: by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger
* Method: off
* Signature: ()V
*/
JNIEXPORT void
JNICALL Java_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger_off(
JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
And implemented it:
#include "by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger.h"
#include <iostream>
#include <windows.h>
JNIEXPORT void JNICALL Java_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger_on
(JNIEnv * env, jobject object) {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
}
JNIEXPORT void JNICALL Java_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger_off
(JNIEnv * env, jobject object) {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2);
}
It does not work! I get exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: by.dev.madhead.bubikopf.desktop.monitortrigger.util.MonitorTrigger.off()V
at by.dev.madhead.bubikopf.desktop.monitortrigger.util.MonitorTrigger.off(Native Method)
at by.dev.madhead.bubikopf.desktop.monitortrigger.App.main(App.java:7)
I was stuck for a bit, but after googling, I've found a solution - use __cdecl instead of __stdcall convention for exported function. So, I've made a very dirty hack:
#define JNICALL __cdecl
And it works!
It was previously defined as __stdcall at jni_md.h. I realize that I'm doing a very bad thing, which harm kittens, but I lack of experience in C/ C++, and I cannot figure out, why I should redefine this? Why standard header (jni_md.h) defines this incorrectly?
For 32 bit DLLs being used by jni, the code has to be compiled without the usual __stdcall adornments - i.e. the code can't have the #N postfix on the symbol name; but it still needs to be compiled in __stdcall mode.
When compiling the dll under mingw, you need to add the option --kill-at to the linker. This is generally passed using -Wl,--kill-at. This will cause the #N postfix to be removed, and so appear as a simple symbol which can be linked at run-time by the JVM. The option can be abbreviated to -Wl,-k as well.
An alternative is to use a map file, which exports the symbols in their unmangled form, which is the mechanism that's used most often when compiling with microsoft's own visual studio compiler.
This is pretty poorly documented, and the resulting error you get when it happens doesn't help too well.
I'd recommend looking at JNA, which makes writing native code wrappers a lot simpler, and in this case would mean no C++ code needed.
The JNA code to accomplish this looks like:
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.WPARAM;
public class JNAMonitorTrigger {
public void monitor(LPARAM param) {
User32.INSTANCE.PostMessage(WinUser.HWND_BROADCAST,
WinUser.WM_SYSCOMMAND,
new WPARAM(0xf170), param);
}
public void on() {
monitor(new LPARAM(-1));
}
public void off() {
monitor(new LPARAM(2));
}
public static void main(String args[]) throws Exception {
JNAMonitorTrigger me = new JNAMonitorTrigger();
me.off();
Thread.sleep(1000);
me.on();
}
};
Even though you're on Windows, you're using GCC, which means this: Is there STDCALL in Linux? is still basically going to apply.
The functions in your file generated by java.h are declared as extern "C"
You have to add it in your cpp file :
extern "C"
JNIEXPORT void JNICALL Java_by_dev_madhead_bubikopf_desktop_monitortrigger_util_MonitorTrigger_on
(JNIEnv * env, jobject object) {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
}
I am trying native methods for the first time....
I had taken a simple programming from this link Click....
nativetest.java
public class nativetest
{
static {
System.loadLibrary("nativetest");
}
public native String sayHello(String s);
public static void main(String[] argv)
{
String retval = null;
nativetest nt = new nativetest();
retval = nt.sayHello("Beavis");
System.out.println("Invocation returned " + retval);
}
}
javac nativetest.java
javah -jni nativetest
Successfully nativetest.h file has been created
nativetest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nativetest */
#ifndef _Included_nativetest
#define _Included_nativetest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nativetest
* Method: sayHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_nativetest_sayHello(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
nativetest.c code
nativetest.c
include "nativetest.h" /*double quotes tells it to search current directory*/
JNIEXPORT jstring JNICALL Java_nativetest_sayHello (JNIEnv *env, jobject thisobject, jstring js)
{
return js;
}
gcc -I/usr/java/jdk1.7.0_13/include -I/usr/java/jdk1.7.0_13/include/linux -o nativetest.so -shared nativetest.c
Successfully shared object file has been created.
when i executed the nativetest, it is showing the following error
java -Djava.library.path=. nativetest
Exception in thread "main" java.lang.UnsatisfiedLinkError: no nativetest in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
at java.lang.Runtime.loadLibrary0(Runtime.java:845)
at java.lang.System.loadLibrary(System.java:1084)
at nativetest.(nativetest.java:4)
Thanx in advance....
On Linux, a shared library's file name should start with "lib", that is, "lib[library_name].so".
Reference: 3.1.1. Shared Library Names
Every shared library has a special name called the ``soname''. The soname has the prefix ``lib'', the name of the library, the phrase ``.so'', followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with ``lib''). A fully-qualified soname includes as a prefix the directory it's in; on a working system a fully-qualified soname is simply a symbolic link to the shared library's ``real name''.
This is my first attempt at JNI. My ultimate goal is to get all tasks currently running on a machine, but need to get even a simple example running. I keep getting this error when I try to execute my main program. I have supplied my simple Java main program, the header file generated, and the error.
I do not know what this DLL could be dependent on. It was initially referencing a DLL I tracked down and placed into system32 (msvcr90.dll).
Here is the command I used to compile the C code as well which produced the DLL, OBJ, LIB, EXP and manifest files.
cl -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\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 <jni.h>
#include <stdio.h>
#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 <jni.h>
/* 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.<clinit>(HelloWorld.java:7)
Exception in thread "main"
The Unsatisfied Link Error can mean many things went wrong. I would use
System.loadLibrary("HelloWorld");
Instead of
System.load();
As TwentyMiles suggested.
Also, when invoking your program you need to (assuming your DLL is on the same directory as your class files:
java -Djava.library.path=. HelloWorld
Here's a simple demo I made that calls a Win32 API function (MessageBox)
Java class
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);
}
}
Generated header file
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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
The C DLL code
#include "CallApi.h"
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#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;
}
Compile instructions
I compile with the Visual C++ express 2008 cl, removing the -ML flag since it causes an exception when the Java code tries to call the native code:
cl /I"c:\Program Files\Java\jdk1.6.0_10\include" /I"c:\Program Files\Java\jdk1.6.0_10\include\win32" -LD CallApi.c -FeCallApi.dll
Then, to run the code:
java -Djava.library.path=. CallApi
I'm not claiming to understand the situation enough to explain it, however some users reported the error when using the "-MD" compiler flag.
For more information see Java Native Interface (JNI) - Impossible to use VS2005 with Java? which discusses this problem and offers possible work-arounds and think techie blog for alternatives.
I believe that you should be using
System.loadLibrary("HelloWorld");
instead of System.load. LoadLibrary will check your system path (not the Java library path) so make sure that HelloWorld.dll is in a directory where it can found. Also note that it does not require the full path, and you don't need to add the dll extension to the end.
I just removed -MD option and compiled it worked like charm
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
If you change the location (package) of your native function declaration from the java side without updating the h file, and the signature of the method in the c++ side, It won't resolve to the method and will throw unsatisfied..
package x;
public class A {
private native void print();
...
}
moved to:
package x.y;
public class A {
private native void print();
...
}
This will require regeneration of the H file (to something like Java_x_y_A_print ).
Note you can change those signatures manually but I won't recommend