@executable_path在Java程序中指向何处 [英] Where does @executable_path point to in a Java program

查看:74
本文介绍了@executable_path在Java程序中指向何处的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试像这样在Mac OS X 10.10.5上的Java中加载本机库:

I'm trying to load a native library in Java on Mac OS X 10.10.5 like this:

System.loadLibrary("SgCore_wrap");

并引发异常:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/nyholku/sgCoreTest/libSgCore_wrap.dylib: dlopen(/Users/nyholku/sgCoreTest/libSgCore_wrap.dylib, 1): Library not loaded: @executable_path/../Frameworks/libsgCore64.dylib

所以我的问题是,如果使用Java程序,@executable_path指向何处?这取决于我是从命令行运行还是在Eclipse中运行的天气?

So my question is where does @executable_path points to in case of a Java program and does this depend on weather I run from command line or within Eclipse?

此外,假设正确的位置是系统中的某个地方"(例如"/Library"),那么在具有嵌入式JVM的可分发Mac OS捆绑包(.app)中,最好的策略是什么?

And further, supposing the correct location is 'somewhere in the system' like say '/Library', what is the best strategy handle this in a distributable Mac OS bundle (.app) with embedded JVM?

我的otool针对涉及的两个库显示的内容(有问题的libSgCore_wrap.dylib中的函数调用libsgCore64.dylib中的函数):

This what my otool shows for the two libraries involved (functions in libSgCore_wrap.dylib call functions in libsgCore64.dylib) in question:

otool -L /Users/nyholku/sgCoreTest/libSgCore_wrap.dylib 
   /Users/nyholku/sgCoreTest/libSgCore_wrap.dylib:
      libSgCore_wrap.dylib (compatibility version 0.0.0, current version 0.0.0)
      /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
      @executable_path/../Frameworks/libsgCore64.dylib (compatibility version 1.0.0, current version 1.0.0)
      /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)                    

,这里是

 tool -L /Users/nyholku/sgCoreTest/libsgCore64.dylib 
    /Users/nyholku/sgCoreTest/libsgCore64.dylib:
       @executable_path/../Frameworks/libsgCore64.dylib (compatibility version 1.0.0, current version 1.0.0)
       /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 157.0.0)
       /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
       /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
       /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.14.0)

作为一个额外的问题,为什么libSgCore_wrap.dylib会引用自身,并且对库应该位于何处意味着什么?

As a bonus question, why does libSgCore_wrap.dylib reference itself and what does it mean/effect as far where the library should be?

推荐答案

似乎您将.dylib从其他应用程序直接复制到用户文件夹,然后尝试使用Java加载它.

Seems that you copy directly the .dylibs from some other application to your user folder and then you're trying to load it with Java.

问题在于这些库上的引用使用的是相对于主可执行文件(另一个应用程序)的@executable_path,并且当Java尝试加载这些库时,使用@executable_path的引用不正确,因此找不到所需的依赖项.

The problem is that the references on these libraries are using @executable_path which is relative to the main executable (the other application) and when Java try to load these libraries the reference using @executable_path are not correct, so dlopen can not find the required dependencies.

针对您的特定情况的可能解决方案是改用@loader_path,因为此变量是相对于引用二进制文件的.

A possible solution for your specific case is to use @loader_path instead since this variable is relative to the referring binary.

因此,如果您只需要这两个库,并且可以使用它们的副本而不必担心它们的更新等,并且它们都在同一目录中,那么您可以尝试复制这些库并从中更改它们的引用使用install_name_tool@executable_path@loader_path.

So if you only need this two libraries, and you can work with a copy of them without worrying about update on theirs etc, and both are on the same directory, then you can try to copy the libraries and change their references from @executable_path to @loader_path using install_name_tool.

正如您在代码中所示,我想两个库都位于同一路径/Users/nyholku/sgCoreTest/中,并且由于您使用的是System.loadLibrary方法,因此您可以正确设置-Djava.library.path=/Users/nyholku/sgCoreTest/.

As you show in your code I suppose that both libraries are in the same path /Users/nyholku/sgCoreTest/ and since you're using System.loadLibrary method you're setting correctly -Djava.library.path=/Users/nyholku/sgCoreTest/.

首先,使用以下命令install_name_tool -change oldReference newReference dylibToChangelibSgCore_wrap.dylib文件中对libsgCore64.dylib的引用更改为您的情况:

First, change the reference to libsgCore64.dylib inside libSgCore_wrap.dylib file using the follow command install_name_tool -change oldReference newReference dylibToChange, in your case:

install_name_tool -change @executable_path/../Frameworks/libsgCore64.dylib @loader_path/libsgCore64.dylib libSgCore_wrap.dylib

然后,在您的情况下,必须使用install_name_tool -id newReference dylibToChange更改libsgCore64.dylib本身的标识符:

Then you must change the identifier of the libsgCore64.dylib itself, using install_name_tool -id newReference dylibToChange, in your case:

install_name_tool -id @loader_path/libsgCore64.dylib libsgCore64.dylib

现在您可以使用这些修改的库,它们将在Java中正确加载.

Now you can use these modified libraries and they will load correctly in Java.

这篇关于@executable_path在Java程序中指向何处的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆