- JNI, загрузка нативных библиотек. Меняем java.library.path на лету
- java.lang.UnsatisfiedLinkError no *****.dll in java.library.path
- 13 Answers 13
- java.lang.UnsatisfiedLinkError: no in java.library.path
- The problem
- What I’ve tried
- Copy the .so file from the server
- Create a symlink
- Add the .so directory to .bashrc
- Print the java.library.path
- Debugging ideas?
- 1 Answer 1
- Java — java.library.path problem on Linux
- 2 Answers 2
- java.library.path has no effect in IntelliJ on linux
JNI, загрузка нативных библиотек. Меняем java.library.path на лету
В подмножестве экосистемы Java, относящейся в основном к JNI (без которого никуда не деться, если приходиться интегрироваться с каким-то legacy или просто редким и специфическим кодом, написанном на С или каком-то другом языке), есть такое понятие, как java.library.path. Вкратце, это в некотором роде аналог classpath, только не для Java классов и *.jar файлов, а для нативных библиотек — системное свойство, которое указывает JVM, где искать эти самые нативные библиотеки (.dll в винде или .so под юниксами).
Свойство это устанавливается один раз, перед запуском JVM, через глобальные system properties, или как ключ -Dname=value для JVM, и после этого оно становится read-only. Точнее, менять-то его можно, но никакого эффекта на работу программы это не окажет, т.к. после того как вы обновите это свойство, JVM не перечитает его и не будет использовать новое значение.
Под катом — про то, как все таки поменять это свойство в рантайме, и немного о том, как собственно работает загрузка нативных библиотек в Java.
Однако, возможность менять java.library.path на лету была бы очень кстати — тогда бы не пришлись много раз генерить, переписывать и перезаписывать скрипты для запуска JBoss-a, например, чтобы отразить в них все нужные пути ДО старта аппсервера.
И такая возможность, изменять эти пути, по которым JVM ищет нативные библиотеки, на самом деле есть. Конкретные приемы показаны тут — blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically и еще вот тут — nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime.
А здесь я опишу сам механизм загрузки, и почему то, что описано по ссылкам, работает. Обычно, нативные библиотеки загружаются через статический инициализатор:
* This source code was highlighted with Source Code Highlighter .
Который выглядит так:
public static void loadLibrary( String libname) <
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
>
* This source code was highlighted with Source Code Highlighter .
И далее в классе Runtime:
synchronized void loadLibrary0(Class fromClass, String libname) <
// Проверяем, разрешено ли загружать данную конкретную библиотеку
SecurityManager security = System.getSecurityManager();
if (security != null ) <
security.checkLink(libname);
>
if (libname.indexOf(( int ) File .separatorChar) != -1) <
throw new UnsatisfiedLinkError( «Directory separator» +
«should not appear in library name: » + libname);
>
ClassLoader.loadLibrary(fromClass, libname, false );
>
* This source code was highlighted with Source Code Highlighter .
Т.е. в итоге, нативные библиотеки загружаются, так же как и обычные классы, через ClassLoader. У класса ClassLoader есть два свойства, в которых кешируются проинициализированные пути поиска.
// The paths searched for libraries
static private String usr_paths[];
static private String sys_paths[];
* This source code was highlighted with Source Code Highlighter .
Код метода ClassLoader.loadLibrary(fromClass, libname, false), довольно длинный, и загроможденный многочисленными проверками, в сокращенном виде выглядит это так.
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute) <
ClassLoader loader = (fromClass == null ) ? null : fromClass.getClassLoader();
if (sys_paths == null ) <
// это то, что нам нужно
usr_paths = initializePath( «java.library.path» );
// а это для тех библиотек, которые загружаются из классов,
// загруженных из boot classpath.
sys_paths = initializePath( «sun.boot.library.path» );
>
// Дальше попытка загрузить библиотеку, и дальше,
// если найти ее так и не удалось, то —
// Oops, it failed
throw new UnsatisfiedLinkError( «no » + name + » in java.library.path» );
>
* This source code was highlighted with Source Code Highlighter .
Таким образом, теперь механизм загрузки нативной библиотеки стал более понятен.
Вы можете либо выставить в null свойство sys_paths у класслоадера, либо просто поменять свойства sys_paths / usr_paths, добавив к ним нужные пути к вашим нативным библиотекам.
Источник
java.lang.UnsatisfiedLinkError no *****.dll in java.library.path
How can I load a custom dll file in my web application? I’ve tried the following:
- Copied all required dlls in system32 folder and tried to load one of them in Servlet constructor System.loadLibrary
- Copied required dlls into tomcat_home/shared/lib and tomcat_home/common/lib
All these dlls are in WEB-INF/lib of the web-application
13 Answers 13
In order for System.loadLibrary() to work, the library (on Windows, a DLL) must be in a directory somewhere on your PATH or on a path listed in the java.library.path system property (so you can launch Java like java -Djava.library.path=/path/to/dir ).
Additionally, for loadLibrary() , you specify the base name of the library, without the .dll at the end. So, for /path/to/something.dll , you would just use System.loadLibrary(«something») .
You also need to look at the exact UnsatisfiedLinkError that you are getting. If it says something like:
then it can’t find the foo library (foo.dll) in your PATH or java.library.path . If it says something like:
then something is wrong with the library itself in the sense that Java is not able to map a native Java function in your application to its actual native counterpart.
To start with, I would put some logging around your System.loadLibrary() call to see if that executes properly. If it throws an exception or is not in a code path that is actually executed, then you will always get the latter type of UnsatisfiedLinkError explained above.
As a sidenote, most people put their loadLibrary() calls into a static initializer block in the class with the native methods, to ensure that it is always executed exactly once:
Источник
java.lang.UnsatisfiedLinkError: no
in java.library.path
The problem
I’ve been trying to run a unit test on my own Mac. The test runs fine on Linux servers, but fails locally with the following trace:
What I’ve tried
Copy the .so file from the server
I’ve copied fedel_client.so from the server to /workspace/dapper/java/lib/native/macosx on my local machine, and added it to the java.library.path :
Create a symlink
I’ve created a symlink from fedel_clinet to fedel_clinet.so , in case that Java is looking for the former (without the .so extension).
Add the .so directory to .bashrc
I’ve tried adding .so directory to PATH :
And to LD_LIBRARY_PATH :
Print the java.library.path
I’ve printed java.library.path , to see if the changes in the Eclipse environment were propagated to the JVM:
The exact values I placed in the Eclipse configuration.
Debugging ideas?
I got the exact same error with all the aforementioned solutions. Any idea how to debug this problem? Can I get a more verbose error message from Java? Is the file not found, or not loaded? If it isn’t loaded, why is that?
1 Answer 1
I may be reading you wrong, but it sounds like you’ve copied the native library ( libfedel_client.so ) from the Linux server to your own Mac. If this is the case, this will certainly not work. You cannot use a Linux native library on your Mac, you will need to recompile it on the Mac to produce a libfedel_client.dylib .
Depending on the version of the Apple Java runtime you’re using, you may need to use the .jnilib extension. Early runtimes used the .jnilib extension instead of .dylib , and both extensions are still supported (although .dylib is now the default.)
Источник
Java — java.library.path problem on Linux
I am able to run a java program with some dependencies from cmd line on my mac, but when I try to run it on a linux SUSE 11 box I have it comes back with:
This is the cmd line I am running:
Any help appreciated!
2 Answers 2
I would recommend to use absolute path for java.library.path . At least you eliminate possible problems with relative path resolution.
Also, just to confirm, you do have Linux library in the lib, right? Mac one will not work.
I’m going go out on a limb and assume(at the risk of a bunch of downvotes) that you are trying to use oracle’s native database driver.
If it is indeed a database driver that you are using, you can bail on the native version and simply include the .jar thin client on your classpath by using the -cp extension. This may require some code changes such that you are not attempting to invoke the native driver.
If you are hell bent on using a native driver or you need to because the code relies on it. you need to make sure that the java.library.path variable is set to a directory containing the binary driver files(typically denoted with a .so extension).
Also make sure these driver files(since they are native binary) have been compiled for your distribution of linux and not just conveniently copied from the mac install.
If you are not doing any of these things feel free to ignore everything I’ve said.
Источник
java.library.path has no effect in IntelliJ on linux
I’m encountering a strange issue with java.library.path on linux and I’m not sure if the problem is with IntelliJ idea or differences in the way java.library.path is used on windows and linux.
The setup is that in Intellij I create a simple JUnit4 test case which looks like this:
In order to set the java.library.path for the given test case I go to Edit Configurations. and set -ea -Djava.library.path=
in VM options , but after running the test case this is the output:
As you can see I try to load the library with System.load(. ) first which works, and I’ve also tried to set the LD_LIBRARY_PATH under Environment variables in Edit Configurations. to the same directory as java.library.path without any success. The issue is not related to dependent libraries not begin found because of the given java.lang.UnsatisfiedLinkError: no dummy in java.library.path error.
When I try this same setup in windows everything works and the library is successfully loaded as long as I’ve set the java.library.path correctly. If the java.library.path is incorrect the test also fails on windows obviously. I have tried both with and without setting LD_LIBRARY_PATH and java.library.path and every combination of the two with no change in results on linux. It almost seems like setting the java.library.path has no effect on linux, but I don’t know if this is a bug in IntelliJ or something related to linux.
EDIT:
In the original test case showed here the library was called libdummy.so and in that case simply removing the lib prefix in the call to System.loadLibrary worked, but in my real case scenario the library does not have a lib prefix, so I have now updated the test case accordingly and recompiled the test library with the name dummy.so and now the test case is failing with the same error again as explained above. Thanks to KC Wong for this tip!
Thanks in advance for any help on this matter!
Источник