tags:

views:

614

answers:

2

Hi,

This my second time coding Java and never referencing any external library before. I follow the JNI examples online and I get UnsatisfiedLinkError when trying to load the dll. I thought that I have to create DLL first before trying to load, but all the examples I've looked they don't mention about creating DLL. Most of them stating that I should create Java code first then native code.

public class ClassSample1 
{
 public native void displayHelloWorld();

 static
 {
  System.loadLibrary("MyLittleJNI");

 } 


 public static void main(String[] args) 
 {
  // TODO Auto-generated method stub
  ClassSample1 classSample1;
  classSample1 = new ClassSample1();
  classSample1.displayHelloWorld();

  System.out.println("Hello");
 }

}

How can I get ride of the error?

A: 

The sample code you provide assumes that there is a DLL in the search path called MyLittleJNI.dll, containing a method displayHelloWorld. The actual C function name in the DLL is decorated using a well defined syntax.

If you get an UnsatisfiedLinkError in loadLibrary(), it is because the JVM cannot find the DLL. You can duck the issue temporarily by specifying the full pathname to the DLL using the System.load(filename) method instead.

Once load or loadLibrary succeeds, you need to make sure that the native function is named correctly. To aid in this, you can use javah to generate a header file containing prototypes for all the native functions in a class.

More information about how to use JNI can be found in here and here.

EDIT: Also, the "Related" column to the right of this questions seems to contain several useful related question.

JesperE
thanks for your responds. I finally got it to link, but the function in my C dll does not display. Maybe I got the function signature wrong.
phillip
If you're function signature is wrong, then calling the function from Java should throw an exception. If not exception is thrown but your output still doesn't appear, then something else is wrong.
JesperE
A: 

I try to create new project again.

So here is JNISample2.java file

public class JNISample2
{

    static
    {
        System.loadLibrary("JNISample2Dll");        
    } 

    public native void displayHelloWorld();

    public static void main(String[] args) 
    {
        System.out.println("from java Hello");

        JNISample2 JNIsample2;
        JNIsample2 = new JNISample2();
        JNIsample2.displayHelloWorld();
    }

}

And here .h file that's generated by the javah -classpath . JNISample2

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

#ifndef _Included_JNISample2
#define _Included_JNISample2
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNISample2
 * Method:    displayHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JNISample2_displayHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Here is my .h file dll that I create VS2005 with MFC app.

// JNISample2Dll.h : main header file for the JNISample2Dll DLL
//

#pragma once

#ifndef __AFXWIN_H__
    #error "include 'stdafx.h' before including this file for PCH"
#endif

#include "resource.h"       // main symbols


#include "JNISample2.h"


// CJNISample2DllApp
// See JNISample2Dll.cpp for the implementation of this class
//

class CJNISample2DllApp : public CWinApp
{
public:
    CJNISample2DllApp();

// Overrides
public:
    virtual BOOL InitInstance();

    DECLARE_MESSAGE_MAP()
};


JNIEXPORT void JNICALL Java_JNISample2_displayHelloWorld(JNIEnv *, jobject);

And here is my .cpp file

// JNISample2Dll.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "JNISample2Dll.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
//TODO: If this DLL is dynamically linked against the MFC DLLs,
//      any functions exported from this DLL which call into
//      MFC must have the AFX_MANAGE_STATE macro added at the
//      very beginning of the function.
//
//      For example:
//
//      extern "C" BOOL PASCAL EXPORT ExportedFunction()
//      {
//          AFX_MANAGE_STATE(AfxGetStaticModuleState());
//          // normal function body here
//      }
//
//      It is very important that this macro appear in each
//      function, prior to any calls into MFC.  This means that
//      it must appear as the first statement within the 
//      function, even before any object variable declarations
//      as their constructors may generate calls into the MFC
//      DLL.
//
//      Please see MFC Technical Notes 33 and 58 for additional
//      details.
//


// CJNISample2DllApp

BEGIN_MESSAGE_MAP(CJNISample2DllApp, CWinApp)
END_MESSAGE_MAP()


// CJNISample2DllApp construction

CJNISample2DllApp::CJNISample2DllApp()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
}


// The one and only CJNISample2DllApp object

CJNISample2DllApp theApp;


// CJNISample2DllApp initialization

BOOL CJNISample2DllApp::InitInstance()
{
    CWinApp::InitInstance();

    return TRUE;
}


JNIEXPORT void JNICALL Java_JNISample2_displayHelloWorld(JNIEnv *, jobject)
{
    MessageBox(NULL, TEXT("In JNISample2Dll"), TEXT("DLL"), 1);
}

After I use command prompt to run: java JNISample2, it display the string "from java Hello", but how come it does not display messagebox that I put inside the .cpp DLL file?

phillip
Don't ask new questions in an answer. Either edit your question, or ask a new question.
JesperE
Your JNI entry point must be compiled with C-linkage, so you need to put `extern "C" { ... }` around the function prototype.
JesperE
thanks for pointing out the rules and regulations. Yeahh I should ask new question..
phillip
when you said your JNI entry point, is it on the Java side or dll side?
phillip
Because I put extern "C" {..} for the Dll function delcaration in .h file. nothing display from dll side
phillip
but if I take out the MessageBox(...) and replace it with printf("In JNISample2DLL"), it shows up in the command prompt windows.
phillip