首页 文章

如何在JNLP网络启动[在Mac上]使用JNA本机库?

提问于
浏览
1

我正在尝试使用JNLP启动Java应用程序;该应用程序包括第三方库(Lab Streaming Layer),它依赖于加载JNA的本机库 .

据我了解,我已经按照所有适当的步骤来完成这项工作:

  • 所有本机库都在JAR文件中,由OS和体系结构分隔 .

  • 所有本机库JAR文件都在服务器上,可从代码库URL访问 .

  • JNLP文件包含 <resources> 元素,其中 osarch 指定了 <nativelib> 元素,其中包含正确的 href 属性 .

  • JNLP文件格式错误并正常启动 .

当我去运行我的应用程序时,我得到报告"Unable to load library 'liblsl32.dylib': Can't obtain InputStream for darwin/liblsl32.dylib"的 java.lang.UnsatisifiedLinkError . 这在程序启动后发生,第一次尝试使用具有本机lib依赖性的库 . 我通过将dylib放在正确的位置,使用单独的非Web启动应用程序更正了此 exact 错误 . 我还尝试将所有dylib重命名为jnilibs,根据以下信息:http://permalink.gmane.org/gmane.comp.java.jna.user/3328,但一切都发生了相同的情况 .

看起来我应该能够在JNLP文件中指定 jna.library.path ,但是我不知道它会是什么,如果它会从启动到发射改变,或者我将如何找出它应该是什么 .

3 回答

  • 0

    Native.getWebStartLibraryPath(name)应该为您提供帮助JNA找到本机库所需的内容 .

    您可以构造绝对路径名,也可以只将路径传递给NativeLibrary.addSearchPath(libName, path) .

    EDITED

    您还需要使用 .jnilib 后缀命名捆绑的OS X共享库,以便Web开始将其识别为本机库 . 这是OS X特有的命名问题 .

  • 0

    Edit 关于使用libo同时支持多个体系结构(32和64位)的单一库的建议,但是当我开发和使用1.8时,底层问题是1.6相关的 .

    根本问题实际上是OSX使用扩展 .jnilib 来扩展它正在加载的库,而不是 .dylib . 这意味着如果您正在制作本机jar,则应确保要加载的库的扩展名为 .jnilib 而不是 .dylib . 一旦你创建了一个包含 .jnilib 的资源jar,那么它将由JNLP类加载器找到;否则JNA使用一些启发式方法来找到它 .

    因此,在创建包含库的jar时,您应确保它具有 .jnilib 扩展名,并且位于 .jar 的根目录,因此,例如,如果我们处理 liblsl32.dylib ,我们将执行类似于以下操作的操作:

    ln -fs liblsl32.dylib liblsl32.jnilib
    jar cf lsl32.jar liblsl32.jnilib
    

    这个 lsl32.jar 是我们要在 .jnlp 文件中引用的资源 . 我们需要签名;所以我使用密钥存储 keystore 和密码 password 使用 myself 身份 .

    jarsigner -storepass password -keystore keystore lsl32.jar myself
    

    对于资源,我必须将引用放入 Macjnlp 文件的资源节:

    <resources os="Mac">
      <nativelib href="darwin.jar"/>
      <nativelib href="lsl32.jar"/>
    </resources>
    

    加载核心JNA库需要 darwin.jar 的引用,加载 liblsl32.jnilib 库需要 lsl32.jar .

    使用以下内容引用库的实例:

    Native.loadLibrary("lsl32", MyClass.class);
    

    应该成功加载它 .

    签署.jar文件时,我确保所有这些文件都在板上具有相关的Codebase / Permissions属性,名为 file.manifest . 该文件包含:

    Permissions: all-permissions
    Codebase: http://localhost/demo
    

    ...确保Codebase与您自己的代码库匹配,并使用以下方法更新jar:

    jar cfm lsl32.jar file.manifest
    

    出于调试目的,如果使用运行jnlp的java进程的lsof,则可以通过加载文件列表中的文件的存在来确定它是否正在使用加载JNLP的库或加载JNA的库,如果它是使用JNLPs机制,然后会在项目列表中引用liblsl32.jnilib,如果它使用JNAs机制,那么就不会提及该文件,因为它被提取到临时文件中 .


    在1.6 VM情况下,如果您不是与VM的架构兼容,并且您通过JNA的加载机制加载,则会收到错误:

    no matching architecture in universal wrapper
    

    在噪音中 .

    如果您运行多种模式(32位/ 64位),您可以将32位和64位库合并到一个库中,并引用它,或者您可以只安装64位库 .

    把两者放在一起,你会做类似的事情:

    lipo -create liblsl.jnilib liblsl32.dylib liblsl64.dylib
    

    然后参考 liblsl ,而不是 liblsl32 .

    我倾向于坚持使用新的VM,即使是所有的安全问题 . 网守阻止我在1.6 VM上加载自签名应用程序而不关闭它,这使得测试环境不稳定 .

    我曾与JNA讨论过的唯一的webstart问题是由于新版JRE版本的安全性增强所致 .

  • 0

    我真的不能称之为答案,但我终于通过暴力破解了这一点 . 我修改了我用来请求.jnilib(而不是原来的.dylib)的库,然后创建了一个名为darwin.jar的本地库,它包含以下结构:

    /META-INF/MANIFEST.MF
    /META-INF/INTERAC.DSA
    /META-INF/INTERAC.SF
    /liblsl32.jnilib
    /liblsl32.dylib    
    /liblsl64.jnilib
    /liblsl64.dylib
    /darwin/liblsl32.jnilib
    /darwin/liblsl32.dylib
    /darwin/liblsl64.jnilib
    /darwin/liblsl64.dylib
    

    不清楚这是什么作用,但显然这个组合包含一些我没有尝试过的事情的排列 . 我没时间或精力进一步排除故障并找到确切的答案 . 我怀疑文件的.dylib版本是不需要的,因为我明确地将代码更改为查找.jnilib,但为了完整起见,它们在那里 .

相关问题