|
Problem(Abstract) |
Native libraries (.dll files on Microsoft® Windows®
platforms, .so files on UNIX® ) never load when configured in a shared
library. This causes a "java.lang.UnsatisfiedLinkException" when
application classes call Java™ Native Interface (JNI) methods.
In addition, native libraries might load only once per Java virtual
machine (JVM™). When this rule is violated, the server JVM emits a message
indicating that "native library <my_native_library> is already
loaded in another classloader." |
|
|
|
Cause |
The first problem occurs because the WebSphere®
Application Server classloaders do not correctly handle the native library
setting in the shared library configuration. This has been repaired in
V5.0.2.3, and an interim solution is provided below.
The second problem occurs when an application attempts to reload a
library that has already been loaded. This situation can occur
inadvertently when utilizing the hot deployment/dynamic reloading
features. It can also occur when restarting applications without shutting
down the server, when the native library appears in the classpath of the
Application Server classloader.
The following solution resolves this problem as well. |
|
|
Resolving the
problem |
To ensure that a native library lib successfully
loads once and only once per application server JVM, place the code that
calls System.loadLibrary(lib) into a static block of a class,
cls. Create a shared library, specifying the path to lib in
the Native Library Path field and the classpath to cls in the
Classpath field. Create a Server classloader and associate the shared
library to this classloader. Follow the detailed instructions below and
note the different steps concerning v5.0.2.2.
- Use the administrative console to configure a shared library: For
V5.0.2.2 or prior releases, perform step a, for subsequent releases
perform step b.
- On the administrative console, click on: Environment > Shared
Libraries
- Click New.
- Enter the name of the shared library.
- Specify the absolute directory (path) containing the native library
DLL or SO in the "Classpath" setting (not the "Native library path"
setting).
- Append the classpath to the class which invokes System.loadLibrary()
in the "Classpath" setting. Make sure to use the correct
platform-specific path delimiter (";" for Windows, ":" for UNIX.)
- On the administrative console, click on: Environment > Shared
Libraries
- Click New.
- Enter the name of the shared library.
- Specify the absolute directory (path) containing the native library
DLL or SO in the "Native library path" setting.
- Enter the classpath to the class which invokes System.loadLibrary() in
the "Classpath" setting.
- For either step a. or b., ensure the path specification does not
contain the name of the DLL file, just the path to the directory
containing the DLL or SO.
- Save your changes.
- Use the administrative console to define or create a classloader on
the application server that will host your applications.
- On the administrative console, click: Application Servers >
(MyAppServer) > classloader.
- Click New. The new classloader appears.
- Click OK and save your changes.
- Use the administrative console to associate the shared library with
the classloader you defined in step 2.
- On the administrative console, click: Application Servers >
(MyAppServer) > Classloader.
- Select the classloader defined in step 2 and click
Libraries.
- Select the library you defined in step 1 and click Add.
- Save your changes.
- Stop and Restart the application server and attempt your scenario.
Step 2 introduces a "Server" classloader between the WebSphere Extensions
and the WebSphere Application classloaders. This classloader exists for
the duration of the Application server (JVM). Because the
System.loadLibrary() invocation is in a static block of a class loaded by
a "Server" classloader, the native library will load exactly once.
A few concerns regarding shared and native libraries:
All applications can safely use the shared library defined above, because
the "Server" classloader exists for the lifetime of the application
server. There is no need to define more than one shared library for any
native library using the above solution.
A second safety concern: Place the native library in a unique path that
will not inadvertently appear in the local classpath of any classloader in
the Application Server runtime environment, and ensure this path contains
no .jar files or classes unrelated to your shared library content.
If you are curious, the classpath of the Application Server classloaders
appears in the output of the classloader dump utility supplied by IBM®
WebSphere Level-2 support. If you place the native library in a path that
appears in the application or WAR classloaders, it is possible that the
native library could get loaded inadvertently by an unexpected
classloader.
For instance, if a servlet loads the library and the library appears in
the classpath of the application classloader, the application classloader
will load the library. When the application is restarted, an exception
will occur when the application attempts to load the library again.
Further, if the library path contains .jar files or classes required by
applications hosted by the server, these artifacts will be loaded by the
"Server" classloader instead of the application classloader (assuming the
default PARENT_FIRST classloader mode) which may cause confusing class
loading issues.
A native library might load unexpectedly if its path appears in the PATH
environment variable of the system. In this case the primordial
classloader (Java bootstrap classloader) -- the root of the WebSphere
classloader tree -- will find the library, and any dependent native
libraries. |
|
|
|
|
Cross Reference information |
Segment |
Product |
Component |
Platform |
Version |
Edition |
Application Servers |
Runtimes for Java Technology |
Java SDK |
|
|
|
|
|
|