VLCJ - Bundling native VLC libraries on 64 bit Linux

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



VLCJ - Bundling native VLC libraries on 64 bit Linux



Background:



I am writing a cross platform audio player in Java. On Linux, I am distributing it in the form of an appimage (https://appimage.org/). I am using VLC/VLCJ as the decoding engine.



The basic guideline for appimages is to include all necessary libraries with the appimage which can't be reasonably expected to be included by default with the distribution. This is done so the user isn't required to resolve dependencies and/or wrestle with versioning differences between libraries and programs. They also recommend testing against the previous version of a handful of Linux distributions to confirm everything works.



Ubuntu 16.04 and Fedora 27.16 do not install libvlc by default. I'm sure this is common for many other distributions. Accordingly, I would like to package libvlc libraries in my appimage.



Issue:



On Linux, I am not able to get vlcj to recognize/find libvlc.so and libvlccore.so unless they are installed through the distribution.


libvlc.so


libvlccore.so



Setup:



I installed VLC through my distribution and my program runs and works properly.



I copied libvlc.so, libvlccore.so, and other associated libraries from their default location in my distribution to a folder within my project.


libvlc.so


libvlccore.so



I added that folder to the Native Library Search path (see code below).



I uninstalled VLC.



I tried to run my program. It crashes with the error pasted below.



Note: I used this same basic method for Windows, and it works perfectly there.



Simplified Code:


String nativeVLCLibPath = Hypnos.getRootDirectory().resolve( "lib/nix/vlc/" ).toAbsolutePath().toString();
System.out.println ( "Trying to look for libraries in: " + nativeVLCLibPath );
NativeLibrary.addSearchPath( RuntimeUtil.getLibVlcLibraryName(), nativeVLCLibPath );



Error Message:



Trying to look for libraries in:
/d/programming/workspace/MusicPlayer/stage/lib/nix/vlc SLF4J: Failed
to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting
to no-operation (NOP) logger implementation SLF4J: See
http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details. Aug 5, 2018 22:14:32 PM net.joshuad.hypnos.Hypnos start
SEVERE: class java.lang.RuntimeException: Exception caught at top
level of Hypnos. Exiting. java.lang.RuntimeException: Failed to load
the native library.



The error was "Unable to load library 'vlc': JNA native support
(linux-amd64/libvlc.so) not found in resource path
(/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/share/java/openjfx/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/icedtea-sound.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar:/usr/share/java/java-atk-wrapper.jar:/d/programming/workspace/MusicPlayer/stage/bin:/d/programming/workspace/MusicPlayer/stage/lib/commons-cli-1.4.jar:/d/programming/workspace/MusicPlayer/stage/lib/fuzzywuzzy-1.1.8.jar:/d/programming/workspace/MusicPlayer/stage/lib/jaudiotagger-2.2.6-SNAPSHOT.jar:/d/programming/workspace/MusicPlayer/stage/lib/commons-io-2.5.jar:/d/programming/workspace/MusicPlayer/stage/lib/jsoup-1.11.2.jar:/d/programming/workspace/MusicPlayer/stage/lib/commons-text-1.1.jar:/d/programming/workspace/MusicPlayer/stage/lib/commons-lang3-3.7.jar:/d/programming/workspace/MusicPlayer/stage/lib/jnativehook-2.0.2.jar:/d/programming/workspace/MusicPlayer/stage/lib/jlastfm.jar:/usr/lib/jvm/java-8-openjdk-amd64/lib/javafx-mx.jar:/d/programming/workspace/MusicPlayer/stage/lib/jna-3.5.2.jar:/d/programming/workspace/MusicPlayer/stage/lib/platform-3.5.2.jar:/d/programming/workspace/MusicPlayer/stage/lib/slf4j-api-1.7.10.jar:/d/programming/workspace/MusicPlayer/stage/lib/vlcj-3.10.1.jar)".



The required native libraries are named "libvlc.so" and
"libvlccore.so".



In the text below represents the name of the directory
containing "libvlc.so" and "libvlccore.so"...



There are a number of different ways to specify where to find the
native libraries:
1. Include NativeLibrary.addSearchPath("vlc", ""); at the start of your application code.
2. Include System.setProperty("jna.library.path", ""); at the start of your application code.
3. Specify -Djna.library.path= on the command-line when starting your application.
4. Add to the system search path (and reboot).



If this still does not work, then it may be necessary to explicitly
add the native library directory to the operating system configuration
- e.g. on Linux this might mean setting the LD_LIBRARY_PATH environment variable, or adding configuration to the "/etc/ld.so.conf"
file or the "/etc/ld.so.conf.d" directory. Of these options, setting
LD_LIBRARY_PATH is the only one that would not require root
privileges.



Finally, it is not possible to mix CPU architectures - it is not
possible for a 64-bit Java Virtual Machine to load 32-bit native
libraries.



More information may be available in the log.



at
uk.co.caprica.vlcj.binding.LibVlcFactory.create(LibVlcFactory.java:198)
at
uk.co.caprica.vlcj.player.MediaPlayerFactory.(MediaPlayerFactory.java:259)
at
uk.co.caprica.vlcj.component.AudioMediaPlayerComponent.onGetMediaPlayerFactory(AudioMediaPlayerComponent.java:177)
at
uk.co.caprica.vlcj.component.AudioMediaPlayerComponent.(AudioMediaPlayerComponent.java:109)
at
net.joshuad.hypnos.audio.VLCAudioPlayer.(VLCAudioPlayer.java:75)
at net.joshuad.hypnos.audio.AudioSystem.(AudioSystem.java:85)
at net.joshuad.hypnos.Hypnos.start(Hypnos.java:726) at
com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at
com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at
com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method) at
com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at
com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at
com.sun.glass.ui.gtk.GtkApplication.lambda$null$5(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:748)



Aug 5, 2018 22:14:32 PM net.joshuad.hypnos.Hypnos exit INFO: Exit
requested: UNKNOWN_ERROR



Exception in Application start method Aug 5, 2018 22:14:32 PM
net.joshuad.hypnos.Hypnos exit INFO: Exit requested: NORMAL



Exception in Application stop method
java.lang.reflect.InvocationTargetException at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at
com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start
method at
com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at
com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748) Caused by:
java.lang.NullPointerException at
net.joshuad.hypnos.Hypnos.exit(Hypnos.java:692) at
net.joshuad.hypnos.Hypnos.start(Hypnos.java:872) at
com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at
com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at
com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method) at
com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at
com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at
com.sun.glass.ui.gtk.GtkApplication.lambda$null$5(GtkApplication.java:139)
... 1 more Exception running application net.joshuad.hypnos.Hypnos



Contents of searched Folder (showing libvlc.so and others are there):


joshua @Joshua-PC /d/programming/workspace/MusicPlayer/stage/lib/nix/vlc
$ ls -l
total 2.5M
-rwxr-xr-x 1 joshua joshua 1.1M May 15 00:26 libvlccore.so
-rwxr-xr-x 1 joshua joshua 1.1M May 15 00:26 libvlccore.so.9.0.0
lrwxrwxrwx 1 joshua joshua 21 Aug 2 22:57 libvlc_pulse.so -> libvlc_pulse.so.0.0.0
lrwxrwxrwx 1 joshua joshua 21 Aug 2 22:57 libvlc_pulse.so.0 -> libvlc_pulse.so.0.0.0
-rwxr-xr-x 1 joshua joshua 14K May 15 00:26 libvlc_pulse.so.0.0.0
-rwxr-xr-x 1 joshua joshua 150K May 15 00:26 libvlc.so
-rwxr-xr-x 1 joshua joshua 150K May 15 00:26 libvlc.so.5.6.0
lrwxrwxrwx 1 joshua joshua 21 Aug 2 22:57 libvlc_vdpau.so -> libvlc_vdpau.so.0.0.0
lrwxrwxrwx 1 joshua joshua 21 Aug 2 22:57 libvlc_vdpau.so.0 -> libvlc_vdpau.so.0.0.0
-rwxr-xr-x 1 joshua joshua 18K May 15 00:26 libvlc_vdpau.so.0.0.0
lrwxrwxrwx 1 joshua joshua 26 Aug 2 22:57 libvlc_xcb_events.so -> libvlc_xcb_events.so.0.0.0
lrwxrwxrwx 1 joshua joshua 26 Aug 2 22:57 libvlc_xcb_events.so.0 -> libvlc_xcb_events.so.0.0.0
-rwxr-xr-x 1 joshua joshua 9.9K May 15 00:26 libvlc_xcb_events.so.0.0.0
drwxr-xr-x 1 joshua joshua 4.0K Aug 2 22:57 lua
drwxr-xr-x 1 joshua joshua 4.0K Aug 2 22:57 plugins
-rwxr-xr-x 1 joshua joshua 11K May 15 00:26 vlc-cache-gen





To rule out the obvious - are you sure the arch of those libraries is definitely 64 bit? (Running file libvlc.so should tell you on most systems.)
– Michael Berry
Aug 7 at 9:22


file libvlc.so





Thanks, yes. They are 64 bit, as is the jvm and the rest of my system.
– JoshuaD
Aug 7 at 17:15




1 Answer
1



I'll bet the distro's version of the native lib has been built with hard-coded paths, possibly absolute paths. Unfortunately, it is not uncommon for libraries to be written to require these -- they're usually passed as flags into the ./configure script or makefile or whatever at build-time. The only fix is to build the lib yourself, or install parallel symlinks/hardlinks, in the distro's lib's expected system dirs, on the target system, to point to your libs. Or execute under chroot, but that is an extreme option that is probably impractical for you.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard