04504: | UnsatisfiedLinkError in components w/ native code in containers, owrun |
Category: Container Status: ClosedSeverity: MEDIUM Reported against release: 0.8 Fixed in release: 0.9
PROBLEM:A user reported getting UnsatisfiedLinkErrors when trying to run a
component that used native code. This occurred whether the component
was run as a standalone process, inside a container, or with
the "owrun" utility. ANALYSIS:Part of the problem has to do with how Java loads native libraries.
Instead of using the classpath, which would make sense, native
libraries are loaded in a platform-dependent way. See the following URL
for details on java.lang.Runtime.loadLibrary():
http://java.sun.com/j2se/1.3/docs/api/java/lang/Runtime.html#loadLibrary
(java.lang.String)
Basically, on Unix platforms, the library must be in a directory
specified in the LD_LIBRARY_PATH environment variable. On Windows
platforms, the library must be in a directory specified in the PATH
environment variable.
This does not mesh well with our installation model, which tries to
avoid setting environment variables.
There are a couple of possible fixes for this problem:
Approach 1: try to trick the library loading mechanism
The mechanism relies on the java.library.path property, which is a read
only property inside the program. (See:
http://developer.java.sun.com/developer/bugParade/bugs/4280189.html).
It might be possible for the container manager can override this
property on the command line when it starts the JVM for a standalone
process, but that wouldn't work for container processes or owrun, since
the directory to add to the path wouldn't be known beforehand.
Therefore this approach is rejected.
Approach 2: a shared directory for native code
In this approach, the Openwings InstallAnywhere installer appends a
single directory to the appropriate path environment variable. The
install service would detect native code libraries in the lib/
directory of components on installation, adn copy the libraries to this
shared directory. This approach obviously would lead to "DLL hell" and
is therefore not workable.
Approach 3: encourage use of Runtime.load()
In this approach, we don't support Runtime.loadLibrary() in Container
Services. Instead, we encourage developers to load native libraries
with Runtime.load() which takes a full path. Pending the resolution of
defect 4058 "Need to propagate installer properties to components",
components will be able to obtain the path name of their lib directory
and construct the full library path name correctly.
Approach 4: set current working directory for standalone processes.
This approach would be used for existing components that use
Runtime.loadLibrary() and can't be modified. The Container Manager
would be modified to set the working directory of the JVM to the lib/
directory of the component when it starts standalone processes. The
assumption is that "." is nearly always on the path environment
variable. (This is probably something that should be done anyway, since
some off the shelf components have the nasty habit of dropping files in
the working directory instead of the temp directory, OpenJMS for
example).
Suggestion: use approaches 3 and 4, since they are complementary. Also,
an example of how to build and deploy components with native code
should be added to the Openwings tutorial. WORKAROUND:Add the "lib" directory of your installed component to the appropriate
environment variable ("PATH" on windows, "LD_LIBRARY_PATH" on Unix).
Example:
setenv LD_LIBRARY_PATH
$LD_LIBRARY_PATH:/usr/local/openwings/myComponent_im/lib
The defect fix only applies to the Container Manager implementation,
therefore this workaround must be used if the component is to be run
using owrun.bat/owrun.csh.
|