【问题标题】:Java JNA Different implementation according to OSJava JNA 根据操作系统的不同实现
【发布时间】:2014-09-26 07:27:03
【问题描述】:

我必须使用 Java JNA 来链接 C 库。这个库有一个 Windows 实现和一个 Linux 实现。对于单个方法,它们与其他方法不同,因为该方法仅由 Windows 版本实现。

MyJnaInterface INSTANCE = (MyJnaInterface) Native.loadLibrary("MyLibrary",
                MyJnaInterface.class);

我想要我的 Java 应用程序的一个版本,这可能有一个接口和 2 个实现,一个用于 windows 操作系统,一个用于 linux 操作系统,显然 linux 实现将有一个空方法。

public interface MyJnaInterface
public class MyJnaWinImpl implements MyJnaInterface
public class MyJnaLinuxImpl implements MyJnaInterface

这在 windows 中有效,在服务启动时的 linux 操作系统中 JNA 尝试在 windows 类中也找到它的本机方法(如果这个类在运行时没有使用),因此它会抛出 UnsatifiedLinkError。 如何解决这个僵局? 我真的无法改变原生库(它会很简单......)

【问题讨论】:

标签: java jna unsatisfiedlinkerror


【解决方案1】:

我建议在您的项目中使用compilation toolbox 来根据 System.getProperty("os.name") 返回的值来编译 java 代码运行时。如果它返回窗口,那么您可以在一个字符串中添加 MyJnaWinImpl 的源代码并将其传递给 JavaSourceCompiler 类。一旦编译加载类并创建实例。在 Linux 上,JavaSourceCompiler 将编译 MyJnaLinuxImpl。确保在创建此实例之前加载了库。

下面是一个小测试代码sn-p。

package test;

import org.abstractmeta.toolbox.compilation.compiler.*;
import org.abstractmeta.toolbox.compilation.compiler.impl.*;
import java.lang.ClassLoader;;


public class test {

    public static void main(String[] args) throws ClassNotFoundException,InstantiationException,IllegalAccessException{
        JavaSourceCompiler javaSourceCompiler = new JavaSourceCompilerImpl();
        JavaSourceCompiler.CompilationUnit compilationUnit = javaSourceCompiler.createCompilationUnit();
        String os = System.getProperty("os.name");
        String SourceCode;
        if ( os.contentEquals("Windows"))
        {
           SourceCode =  "package com.test.foo;\n" +
          "import MyJnaInterface.*;" +
          "import MyJnaWinImpl " +
          "public class Foo implements MyJnaWinImpl  {\n" +
          " public native void check();\n" +
          "    }";
        }
        else
        {
               SourceCode =  "package com.test.foo;\n" +
                          "import MyJnaInterface.*;" +
                          "import MyJnaLinuxImpl  " +
                          "public class Foo implements MyJnaLinuxImpl   {\n" +
                          //" public native void check();\n" +
                          "    }";  
        }
        compilationUnit.addJavaSource("com.test.foo.Foo", SourceCode);
        ClassLoader classLoader = javaSourceCompiler.compile(compilationUnit);
        Class fooClass = classLoader.loadClass("com.test.foo.Foo");
        Object foo = fooClass.newInstance();
    }

}

【讨论】:

    【解决方案2】:

    我使用 static{} 块解决了。

    public interface MyJnaInterface;
    public interface MyJnaInterfaceWin implements MyJnaInterface; // this has the WinMethod method
    
    ...
    
        private static MyJnaInterface INSTANCE;
    
        static{
            if(SystemUtils.IS_OS_LINUX){
                INSTANCE=(MyJnaInterface) Native.loadLibrary("MyLibrary",MyJnaInterface.class);
            }else{
                INSTANCE=(MyJnaInterfaceWin) Native.loadLibrary("MyLibrary",MyJnaInterfaceWin.class);
            }
        }
    
    
    ...
    
    public static void WinMethod(){
                if(!SystemUtils.IS_OS_LINUX) ((MyJnaInterfaceWin)INSTANCE).WinMethod());
            }
    

    【讨论】:

      【解决方案3】:

      我假设您使用的是直接映射,因为接口映射在您调用它之前不会查找您的函数。

      编写一个带有基本实现的基类,然后是一个包含附加映射的派生类。只加载您知道存在底层函数的派生类。

      class BaseInterface { 
          public native void nativeMethod();
          public void extendedMethod() { /* empty stub */ }
      }
      
      class ExtendedInterface extends BaseInterface {
          public native void extendedMethod();
      }
      
      if (needExtendedInterface) {
          lib = /* load extended library */
      }
      else {
          lib = /* load base library */
      }
      

      【讨论】:

      • 在 linux 版本上调用 Native.loadLibrary 时会失败,因为 C 库没有实现可选方法。
      • 您需要确保仅在支持它的平台上加载/引用ExtendedInterface
      猜你喜欢
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多