I am trying to setup a simple dll that will allow me to run C++ code from Java, to start I chose to create the function HelloWorld, I can get the library to compile and load but when Java calls the native method "hello()" it throws the exception java.lang.UnsatisfiedLinkError.

How can I fix this?

My Files:
Helloworld.cpp

#include "Helloworld.h"

	JNIEXPORT void JNICALL Java_JPokerBot_Process_hello (JNIEnv *, jobject) {
		printf("Hello world!\n");
		return;
	}

Helloworld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JPokerBot_Process */

#ifndef _Included_JPokerBot_Process
#define _Included_JPokerBot_Process
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     helloworld
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_helloword_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

helloworld.java

import java.util.*;

class helloworld {
	//Native method declaration
	public native void hello();

	public static void main(String args[]) {
		
		try {
			helloworld hello = new helloworld();
			helloworld.hello();
		} catch(UnsatisfiedLinkError e) {
			System.out.println(e);
		}
	}
}

My Files Cleared of typos:
Helloworld.cpp

#include "Helloworld.h"

	JNIEXPORT void JNICALL Java_helloworld_hello (JNIEnv *, jobject) {
		printf("Hello world!\n");
		return;
	}

Helloworld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>

#ifndef _Included_helloworld
#define _Included_helloworld
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     helloworld
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_helloworld_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

helloworld.java

import java.util.*;

class helloworld {
	//Native method declaration
	public native void hello();

	public static void main(String args[]) {
		
		try {
			helloworld hello = new helloworld();
			helloworld.hello();
		} catch(UnsatisfiedLinkError e) {
			System.out.println(e);
		}
	}
}
#include "Helloworld.h"

	JNIEXPORT void JNICALL Java_helloworld_hello (JNIEnv *, jobject) {
		printf("Hello world!\n");
		return;
	}

Now I am curious, how did that compile, if I haven't completely forgotten my C++, shouldn't there be a name given to the parameters of the function in the definition like this:-

JNIEXPORT void JNICALL Java_helloworld_hello (JNIEnv *env, jobject obj) {

BTW another question, where are you loading the DLL ? Before using the "native" method (in your java code) you need to load the library, by using either the System.load(String dllFile) or System.loadLibrary(String libName) methods.

Edited 6 Years Ago by stephen84s: n/a

That was some hacked together code let me post a more recent attempt using NativeCall.

Attempting to retrieve the PID of a process given the file name.
NativeImports.h:

namespace NativeImports
{
    class NativeImports
    {
    public:
		static __declspec(dllexport) int getPids(char* procName);
	};
}

NativeImports.cpp:

#include "NativeImports.h"

#include <windows.h>
#include <psapi.h>
#include <string>
#pragma comment( lib, "Psapi.lib" )

using namespace std;

namespace NativeImports
{
	int NativeImports::getPids(char* procName) {
		int PID[150];
		DWORD aProcesses[1024], cbNeeded, cProcesses;
		unsigned int i, count, exes = 0;

		if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
			return -1;

		cProcesses = cbNeeded / sizeof(DWORD);

		for ( i = 0; i < cProcesses; i++ ) {
			if( aProcesses[i] != 0 ) {
				PID[count] = (int)(aProcesses[i]);
				count++;
			}
		}

		for( i = 0; i < cProcesses; i++ ) {
			HANDLE hProcess = OpenProcess(PROCESS_VM_READ,FALSE, PID[i]);
			char* name;
			PDWORD size;
			bool pass = QueryFullProcessImageName( hProcess, 0,(LPWSTR)(name), size);
			string str1 = ( (const char*)(name) );
			string::size_type location = str1.find( procName, 0 );
			if( location != string::npos )
				return PID[i];
		}
		
		return 0;
		
	}
}

DllTest.java:

/**
 * @(#)DllTest.java
 *
 *
 * @author 
 * @version 1.00 2010/6/27
 */
package JPokerBot;

import com.eaio.nativecall.*;
import java.io.IOException;

class DllTest {
	//Native method declaration
	
	public static void main(String args[]) {
		try {
	    	NativeCall.init();
			IntCall getPids = new IntCall("NativeCall.dll", "getPids()" );
			int pid = getPids.executeCall(new Object[] { "client" });
			System.out.println(pid);
		} catch (IllegalArgumentException e) {
			System.out.println(e);
		} catch (NullPointerException e) {
			System.out.println(e);	
		} catch (IOException e) {
			System.out.println(e);	
		}
	}
}

When I run the code I get a java.lang.NullPointerException. Help me please.

} catch (IllegalArgumentException e) {
			System.out.println(e);
		} catch (NullPointerException e) {
			System.out.println(e);	
		} catch (IOException e) {
			System.out.println(e);	
		}

Instead of System.out.println(e) use e.printStackTrace() , as just instead of the name of the exception, it will give you exactly on what line the exception occurred. Right now any suggestion I give would involve pure guess work as I do not know on what line the 'NullPointerException' was encountered.

I do not know C++ but I have done some work with the procedural language PL/I and calling it from Java. I had these error many times and solved them by correctly naming the DLL entry points in my PL/I code and appropriate names in Java. For me, the names were not intuitive nor correctly documented by IBM. The name (for me at least ) MUST contain the package name. I wrote this up in a PL/I newsletter
http://members.dodo.com.au/~robin51/pli-n11.htm
which is free to read on internet, this may help. IMHO is it purely a problem of correctly entry point identification, straight forward but not easy.

} catch (IllegalArgumentException e) {
			System.out.println(e);
		} catch (NullPointerException e) {
			System.out.println(e);	
		} catch (IOException e) {
			System.out.println(e);	
		}

Instead of System.out.println(e) use e.printStackTrace() , as just instead of the name of the exception, it will give you exactly on what line the exception occurred. Right now any suggestion I give would involve pure guess work as I do not know on what line the 'NullPointerException' was encountered.

I updated my file:
DllTest.java

/**
 * @(#)DllTest.java
 *
 *
 * @author 
 * @version 1.00 2010/6/27
 */
package JPokerBot;

import com.eaio.nativecall.*;
import java.io.IOException;

class DllTest {
	//Native method declaration
	
	public static void main(String args[]) {
		try {
	    	NativeCall.init();
			IntCall getPids = new IntCall("NativeImports.dll", "getPids" );
			int pid = getPids.executeCall(new Object[] { "client" });
			System.out.println(pid);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (NullPointerException e) {
			e.printStackTrace();	
		} catch (IOException e) {
			e.printStackTrace();	
		} catch (UnsupportedOperationException e) {
			e.printStackTrace();
		} catch (SecurityException e) { 
			e.printStackTrace();
		} catch (UnsatisfiedLinkError e) {  
			e.printStackTrace();
		} catch (sun.misc.ServiceConfigurationError e) { 
			e.printStackTrace();
		}
	}
}

My new error is

java.lang.UnsupportedOperationException
    at com.eaio.nativecall.NativeCall.init(NativeCall.java:131)
    at JPokerBot.DllTest.main(DllTest.java:18)

Thank you for helping me.

I am confused by your code. Did you read my article about PLI?
Please explain how your built your DLL and how the C++ code is called from Java including entry names and package names.

This article has been dead for over six months. Start a new discussion instead.