Back to UnsatisfiedLinkError: libxuggle-xuggler-io-2.dll: Can't find dependent libraries

112 views
Skip to first unread message

tevch

unread,
Apr 30, 2009, 1:01:10 AM4/30/09
to xuggler-users
This is really confusing stuff
I mean, i understand - there has to be a PATH env variable(in windows)
for libraries to be found
But isn't it a huge restriction to how software can be deployed?
Lets say "java.library.path" contains path to libxuggle-xuggler-
io-2.dll - so xuggle location is known, right?

why do we need another native PATH? or LD_LIBRARY_PATH?

i know, "java.library.path" is known in java, but why not assume in
native code that libraries are in the same dir as parent dll/so? and
if not found - try PATH/LD_LIBRARY_PATH

sorry, its not a criticism, just trying to figure out a way for better
web deployment, without setting up native/local variables.

Thanks

Art Clarke

unread,
Apr 30, 2009, 11:10:56 AM4/30/09
to xuggle...@googlegroups.com
This is something that Robert and I have lamanted often.  The problem is that java.library.path can only locate the FIRST shared library to load.  If that library then loads other shared libraries, it will look for those dependencies in a PATH/LD_LIBRARY_PATH specified set of locations.  Worse, on most operating systems, the search-path it searches is set at process start time and cannot be modified by the running process (ugh).

For example it turns out that xuggle-xuggler.jar loads (via Java) libxuggle-xuggler-2.dll, which in turn loads (via the OS) libxuggle-xuggler-io-2.dll, libavcodec-?.dll, libavformat-?.dll, libavutil-?.dll and libswscale-?.dll.  These in turn load (via the OS) libmp3lame-0.dll, libspeex-0.dll and libfaad-?.dll.  Normally "java.library.path" will only find the first dll (libxuggle-xuggler-2.dll) and all the rest will be searched for by the OS.  So we need to have people install a native component first.

There is a potential way around this in Microsoft Windows; in theory we could put all DLLs into the JAR file directly because (I believe) Windows will look for a DLL first in that path of the loading DLL, and if not found will only then search the PATH variable.  Unfortunately this convention does not work on other operating systems (Mac, and the N-different flavors of Linux).  Worse, what versions of which .so and .dylib files should we include in the jar file for those systems?  And what about 32-bit versus 64-bit versions?  And what happens to the size of our JAR file?

Another thing we considered is creating one bill DLL for all Xuggler and dependencies but this has the effect of (a) meaning LGPL builds of Xuggler are impossible, (b) has known issues with linking non-DLL versions of FFMPEG on Microsoft Windows and (c) removes the ability for people to use their own version of ffmpeg with Xuggler (which is really the same as (a)).

The fact is Xuggle has a native component and always will in the future, and because of this issue we require setting up the PATH/LD_LIBRARY_PATH variables (it's worth nothing that all other similar JNI products -- Sun's JMF, JFFMPEG, FobS, etc -- all have the same restriction).  To make things a little easier, we actually make setting "java.library.path" optional -- if you don't set it (as most people do seem to forget to) we'll search PATH, LD_LIBRARY_PATH or DYLD_LIBRARY_PATH for you.

I hope that answers your question.  I am open to approaches that work around this problem that keep current levels of functionality but make it easier for web deployment -- the problem is I haven't heard of any.

- Art
--
http://www.xuggle.com/
xu‧ggle (zŭ' gl) v. To freely encode, decode, and experience audio and video.

Use Xuggle to get the power of FFMPEG in Java.

tevch

unread,
Apr 30, 2009, 12:59:59 PM4/30/09
to xuggler-users
Thanks for very detailed explanation, it all makes sense

But i believe there is another approach, just tested it and it works
like a charm

Basically instead of loading xuggle from the top (libxuggle-
xuggler-2.dll/so) we can load it from the bottom, starting from
dependencies(avutil.dll. libmp3lame.dll etc)
Bottom dependencies don't have their own dependent dll's, so they will
be loaded.

And when it comes to loading libxuggle-xuggler-2.dll - all
dependencies will be already loaded, so there will be no issue

Here is the order:

private void loadXuggler() {
JNILibraryLoader.loadLibrary("avutil", null);
JNILibraryLoader.loadLibrary("avutil-50", null);
JNILibraryLoader.loadLibrary("avutil-50.2.0", null);
JNILibraryLoader.loadLibrary("libmp3lame-0", null);
JNILibraryLoader.loadLibrary("libspeex-1", null);
JNILibraryLoader.loadLibrary("libspeexdsp-1", null);
JNILibraryLoader.loadLibrary("libx264-66", null);
JNILibraryLoader.loadLibrary("libxuggle-ferry-2", null);


JNILibraryLoader.loadLibrary("swscale", null);
JNILibraryLoader.loadLibrary("swscale-0", null);
JNILibraryLoader.loadLibrary("swscale-0.7.1", null);

JNILibraryLoader.loadLibrary("avcodec", null);
JNILibraryLoader.loadLibrary("avcodec-52", null);
JNILibraryLoader.loadLibrary("avcodec-52.22.3", null);

JNILibraryLoader.loadLibrary("avformat", null);
JNILibraryLoader.loadLibrary("avformat-52", null);
JNILibraryLoader.loadLibrary("avformat-52.32.0", null);

JNILibraryLoader.loadLibrary("avdevice-52", null);
JNILibraryLoader.loadLibrary("avdevice-52.1.0", null);

JNILibraryLoader.loadLibrary("libxuggle-xuggler-2", null);
JNILibraryLoader.loadLibrary("libxuggle-xuggler-io-2", null);
}

Art Clarke

unread,
Apr 30, 2009, 1:36:42 PM4/30/09
to xuggle...@googlegroups.com
Hi there,

That approach will work on Windows for exactly the set of dependencies you have built, because the first loaded copy of a DLL in Windows is automatically shared by all successive loaders (see "Dll Hell" in Wikipedia for the downside of this).

Unfortunately given Xuggler's ability to support versions of ffmpeg we haven't installed ourselves (a requirement to maintain our LGPL licensing status on non-windows systems) we can't programatically determine what our dependencies are -- they are built up dynamically by either our build system (if you used our captive libraries) or by other people's build systems (if you installed your own libx264, libmp3 or something else). 

Put in other words, when we (from java) ask to load libxuggle-xuggler-2.dll, we don't know if libmp3lame.dll exists on your system, or libx264 or (believe it or not) even libxuggle-xuggler-io-2.dll.  The OS's dynamic library loader knows that, but it's not telling us.

So your approach will work on Windows for EXACTLY the set of dependencies you have installed.  However, we can't guarantee that everyone has that set installed :(

To help a little with that, here are the general requirements we tried to hit:
  1. Xuggler must work on Linux, Mac and Windows (needed for distribution purposes).
  2. Xuggler native code must be able to dynamically link with a user-compiled version of ffmpeg and any other optional libraries (needed for LGPL license) on all supported systems.
  3. Xuggler should degrade gracefully at runtime if optional components are not present (e.g. if libx264 is not compiled in, we'll just return -1 when you attempt to open the ICodec.ID.H264 codec for encoding, as opposed to crashing).
  4. If special configuration is required, Xuggler should prefer doign it at install time over run-time (hence we prefer PATH over -Djava.library.path on every Java run).  This is so that, assuming you're run the installer, things just "work" out of the box.
And here's the one thing what we allow ourselves to achieve all that:
  1. Installers must set up the dynamic run-time path for NATIVE libraries in a standard way for the OS we're on.  Just like most other JNI libraries out there :)
- Art
Reply all
Reply to author
Forward
0 new messages