Search code examples
javaeclipsejava-native-interface

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.printer.PrinterWinAPI.GetStatus(Ljava/lang/String;)J


Here is my problem: I'm trying to use JNI in my Java project as a way of talking to the Win32 API. I get this error at run time in eclipse:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.printer.PrinterWinAPI.GetStatus(Ljava/lang/String;)J
at com.printer.PrinterWinAPI.GetStatus(Native Method)
at com.printer.PrinterWinAPI.<init>(PrinterWinAPI.java:14)
at com.printer.PrinterWinAPI.main(PrinterWinAPI.java:25)

But what is really weird about my issue is that I can successfully compile my project using the cmd:

javac PrinterWinAPI.java

Then the program runs fine by running:

java PrinterWinAPI

From what I understand, eclipse successfully locates my .dll file but can't find the GetStatus() function inside the file. I tried to compile it using visual studio both in x86 and x86_64 AND mingw gcc in both x86 and x86_64. Here are my files:

The java file which implements the JNI interface: PrinterWinAPI.java

package com.printer;

public class PrinterWinAPI {
    static {
        System.load("C:\\GetPrinterStatus.dll");
    }

    public Long         status;
    public String       name;

    public PrinterWinAPI(String printerName) {
        this.name = printerName;
        this.status = this.GetStatus(this.name);
    }

    private native long GetStatus(String str);

    public static void main(String[] args) {
        PrinterWinAPI printer = new PrinterWinAPI("PRINTER NAME EXAMPLE");
        System.out.println(printer.status);
    }
}

PrinterWinAPI.h, generated using javah PrinterWinAPI:

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

#ifndef _Included_PrinterWinAPI
#define _Included_PrinterWinAPI
#ifdef __cplusplus extern "C" {
#endif /*  * Class:     PrinterWinAPI  * Method:    
GetStatus  * Signature: (Ljava/lang/String;)J  */ 
JNIEXPORT jlong JNICALL Java_PrinterWinAPI_GetStatus   (JNIEnv *, jobject, jstring);

#ifdef __cplusplus }
#endif
#endif

and here is the PrinterWinAPI.c file itself:

#include "PrinterWinAPI.h"   // Generated
#include <windows.h>
#include <wincon.h>
#include <winspool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <io.h> 

// Implementation of the native method
JNIEXPORT jlong JNICALL Java_PrinterWinAPI_GetStatus(JNIEnv *env, 
jobject thisObj, jstring str) {
        //some stuff...
    return (int64_t)dwStatus;
 }

Once again, the program is compiling and running fine using javac, javah and java from the command prompt, I'm 99% sure the issue is from eclipse but I really don't know where to start. I spent several hours searching for a solution online but couldn't find anything. Why can't eclipse run my project but the java binaries ran manually can?

My jre/jdk is build 1.8.0_101-b13 64-bits

Eclipse: Oxygen.3a Release (4.7.3a)

OS: Windows 7 64-bits


Solution

  • @user2543253 Thank you it worked! It was correctly compiling because my java file wasn't in a package so the header was correct but since the java file was nested in a package in my project the correct header was Java_com_printer_PrinterWinAPI_GetStatus instead of Java_PrinterWinAPI_GetStatus.