Java load library windows

Loading dll using loadLibrary

I am currently maintaining a Java communication library which wraps the functionality offered by some dll via JNI. At some point, in Java, I need to load the JNI wrapper to forward my requests and finally call the native library. Currently, this is accomplished by calling

As stated here, this should always find MyLibrary if it is placed somewhere within java.library.path . Currently, my java.library.path seems to include some Java specific folders as well as all directories specified in the %PATH% environment variable:

My problem now is that even though MyLibrary is placed in C:\MyFolder\Common64; the above loadLibrary call yields an UnsatisfiedLinkError and I cannot seem to understand why. It is however found when I put it into the System32 folder, or if I instead call load while specifying the path absolutely:

I tried to mess around with the java.library.path during runtime using the sys_path trick suggested in the answers given here and here. The following works flawlessly:

So, if I replace the entire java.library.path property with a custom path the dll is successfully loaded. However, this is not the desired behavior, as I want to find the dll dynamically by adding the correct directory to %PATH%. Furthermore, adding my custom path to java.library.path like so

also does not work.

Currently I am trying to make this work on a Win7 64-bit machine. My dll is also compiled as x64, if that’s relevant.

The general procedure works flawlessly when I compile my Java library in x86 mode and copy the according JNI dll to C:\MyFolder\Common32\ and add that directory to %PATH%.

JNI, загрузка нативных библиотек. Меняем java.library.path на лету

В подмножестве экосистемы Java, относящейся в основном к JNI (без которого никуда не деться, если приходиться интегрироваться с каким-то legacy или просто редким и специфическим кодом, написанном на С или каком-то другом языке), есть такое понятие, как java.library.path. Вкратце, это в некотором роде аналог classpath, только не для Java классов и *.jar файлов, а для нативных библиотек — системное свойство, которое указывает JVM, где искать эти самые нативные библиотеки (.dll в винде или .so под юниксами).

Читайте также:  Vcredist x32 для windows

Свойство это устанавливается один раз, перед запуском 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» );
>

Читайте также:  Windows audio состояние выполняется

* This source code was highlighted with Source Code Highlighter .

Таким образом, теперь механизм загрузки нативной библиотеки стал более понятен.

Вы можете либо выставить в null свойство sys_paths у класслоадера, либо просто поменять свойства sys_paths / usr_paths, добавив к ним нужные пути к вашим нативным библиотекам.

Java.lang.Runtime.loadLibrary() Method

Description

The java.lang.Runtime.loadLibrary(String filename) method loads the dynamic library with the specified library name. A file containing native code is loaded from the local file system from a place where library files are conventionally obtained. The details of this process are implementation-dependent. The mapping from a library name to a specific filename is done in a system-specific manner.

First, if there is a security manager, its checkLink method is called with the libname as its argument. This may result in a security exception. The method System.loadLibrary(String) is the conventional and convenient means of invoking this method. If native methods are to be used in the implementation of a class, a standard strategy is to put the native code in a library file (call it LibFile) and then to put a static initializer −

within the class declaration. When the class is loaded and initialized, the necessary native code implementation for the native methods will then be loaded as well. If this method is called more than once with the same library name, the second and subsequent calls are ignored.

Declaration

Following is the declaration for java.lang.Runtime.loadLibrary() method

Parameters

libname − the name of the library.

Return Value

This method does not return a value.

Exception

SecurityException − if a security manager exists and its checkLink method doesn’t allow loading of the specified dynamic library

UnsatisfiedLinkError − if the library does not exist

NullPointerException − if libname is null

Example

The following example shows the usage of lang.Runtime.loadLibrary() method.

Let us compile and run the above program, this will produce the following result −

Java load library windows

(Linux/CentOS/Solaris)
How to Load a Java Native/Shared Library (.so)

There are several ways to make it possible for the Java runtime to find and load a native shared library (.so) at runtime. I will list them briefly here, followed by examples with more explanation below.

  1. Call System.load to load the .so from an explicitly specified absolute path.
  2. Copy the shared library to one of the paths already listed in java.library.path
  3. Modify the LD_LIBRARY_PATH environment variable to include the directory where the shared library is located.
  4. Specify the java.library.path on the command line by using the -D option.

1. Call System.load to load the shared library from an explicitly specified absolute path.

This choice removes all uncertainty, but embeds a hard-coded path within your Java application. Example:

2. Copy the shared library to one of the paths already listed in java.library.path

To view the paths listed in java.library.path, run this Java code:

Читайте также:  Tablet samsung com windows

Note: The java.library.path is initialized from the LD_LIBRARY_PATH environment variable.

The loadLibrary method may be used when the directory containing the shared library is in java.library.path. To load «libchilkat.so», call System.loadLibrary(«chilkat»), as shown below.

3. Modify the LD_LIBRARY_PATH environment variable to include the path where the Chilkat shared library is located.

For Bourne Shell, K Shell or Bash, type:

For C Shell, type:

4. Specify the java.library.path on the command line by using the -D option.

For example:

Privacy Statement. Copyright 2000-2018 Chilkat Software, Inc. All rights reserved.

(Regarding the usage of the Android logo) Portions of this page are reproduced from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License .

Software components and libraries for Linux, MAC OS X, iOS, Android™, Solaris, RHEL/CentOS, FreeBSD, MinGW
Azure, Windows 10, Windows 8, Windows Server 2012, Windows 7, 2003 Server, 2008 Server, etc.

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

14 Answers 14

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:

Оцените статью