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);
		}
	}
}

Recommended Answers

All 7 Replies

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.

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.