繁体   English   中英

Ecplise Java JNI,java.lang.UnsatisfiedLinkError加载dll

[英]Ecplise Java JNI, java.lang.UnsatisfiedLinkError loading dll

我在加载打印机dll时遇到问题。 我有一个打印机制造商的dll文件(JniPrinterStatusLib.dll)。 我写了像打印机制造商建议的代码。 代码是:

package com.printer.test

public class JniPrinterStatus {
    static{
        System.loadLibrary("JniPrinterStatusLib");
    }

    public native int GetStatus(String printer);
}
package com.printer.test

public class TestSample {
    public static void main(String[] args) {
        int status;
        String printer = "MY PRINTER";
        JniPrinterStatus jps = new JniPrinterStatus();

        System.out.println("PRINTER NAME = " + printer);

        status = jps.GetStatus(printer);
        if (status == -1) {
            System.out.println("status = -1");
        }
        else if (status == 0) {
            System.out.println("status = NORMAL");
        }
        else if ((status & 0x00000080) != 0) {
            System.out.println("status = PRINTER_STATUS_OFFLINE");
        }
        else if ((status & 0x00400000) != 0) {
            System.out.println("status = PRINTER_STATUS_DOOR_OPEN");
        }
        else if ((status & 0x00000010) != 0) {
            System.out.println("status = PRINTER_STATUS_PAPER_OUT");
        }
        else if ((status & 0x00000800) != 0) {
            System.out.println("status = PRINTER_STATUS_OUTPUT_BIN_FULL");
        }
        else if ((status & 0x00000040) != 0) {
            System.out.println("status = PRINTER_STATUS_PAPER_PROBLEM");
        }
   }
}

我用Eclipse运行代码,我把dll库放在文件夹项目中,错误是

PRINTER NAME = MY PRINTER
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.printer.test.JniPrinterStatus.GetStatus(Ljava/lang/String;)I
    at com.printer.test.JniPrinterStatus.GetStatus(Native Method)
    at com.printer.test.TestSample.main(TestSample.java:10)

如果我将源代码“com.printer.test”移动到默认包,代码将工作并显示:

PRINTER NAME = MY PRINTER
status = -1

我不知道怎么可能。 如果我从命令提示符编译并运行代码而没有包它可以工作。

问题出在哪儿?

谢谢

对不起,实际上我想写评论,但由于我的声誉仍然很低,我不得不尝试猜测答案。

  • 应该没有必要重新编译DLL - 它只是一些要调用的本机代码。
  • 加载dll的类的java包也不应该有所作为。

您必须注意您的系统架构:64位DLL文件将在32位JRE中失败,反之亦然。 确保您的JRE架构与dll架构相匹配。

另一件需要考虑的事情是你的工作目录。 Eclipse可能使用的工作目录与从控制台运行程序时使用的工作目录不同。

最后但并非最不重要的,请查看您的java.library.path变量。

此页面也可能有所帮助: https//www.chilkatsoft.com/java-loadLibrary-Windows.asp我将介绍所有细节。

来自类UnsatisfiedLinkErrorjavadoc ...

如果Java虚拟机无法找到声明为native的方法的适当本机语言定义,则抛出该异常。

这意味着找不到函数Java_com_printer_test_JniPrinterStatus_GetStatus

java.lang.System方法loadLibrary通常搜索[System]属性“java.library.path”中列出的目录。 对于Windows机器,此属性的值通常是PATH环境变量的值。

因此,我建议在代码中打印出该属性的值,以查看它是否包含包含DLL的目录。 如果没有,则需要通过重新定位DLL或更改PATH环境变量或使用-Djava.library.path=...选项启动java程序来解决此问题。 之后,您需要检查本机方法的签名。 Dependency Walker是我在工作中用来完成此任务的工具。

编辑重新阅读您的问题,我觉得我没有准确地解决您的问题,所以让我补充一下......

Eclipse的默认行为是将资源文件(如DLL)复制到输出文件夹。 因此,如果您将DLL放在文件夹src\\com\\printer\\test ,它将获得复制到bin\\com\\printer\\test文件夹。 我的猜测是当前的工作目录,即. 在你的“java.library.path”中,这就是当你的java代码在默认包中时它可以工作的原因。

预期的Java类包在JNI库中进行了硬编码。 在您的情况下,它是默认包。

让我扩展一下。 当在JNI库中实现本机方法时,必须使用以下格式的名称创建公共C函数:

Java_com_mypackage_MyClass_MyMethod

换句话说,JNI库无法为任意包中的类提供方法 - 仅适用于JNI库作者所考虑的包中的类。

在你的情况下,它是默认的。 C函数转到Java_JniPrinterStatus_GetStatus 如果调用类MyPrinterStatus ,或将其放入com.foobar包中,则JNI运行时将无法将C函数与声明的Java本机方法相关联。 这就是JNI的设计方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM