2

I am attempting to load a native library using JNA, using this line:

MPV INSTANCE = Native.load("mpv", MPV.class, Map.of(Library.OPTION_STRING_ENCODING, "UTF-8"));

This works absolutely fine on an Ubuntu 20.04 that I installed in a Hyper-V VM on my main machine, but for some reason fails on an Ubuntu 20.04 native install.

The logs where it fails look like this:

    Looking in classpath from {0} for {1}
    Found library resource at {0}
    Extracting library to {0}
    Trying {0}
    Found jnidispatch at {0}
    Looking for library 'mpv'
    Adding paths from jna.library.path: null
    Trying libmpv.so
    Loading failed with message: libmpv.so: cannot open shared object file: No such file or directory
    Adding system paths: [/usr/lib/x86_64-linux-gnu, /lib/x86_64-linux-gnu, /usr/lib64, /lib64, /usr/lib, /lib, /lib/i386-linux-gnu, /usr/lib/x86_64-linux-gnu/libfakeroot]
    Trying libmpv.so
    Loading failed with message: libmpv.so: cannot open shared object file: No such file or directory
    Looking for version variants
    Trying /usr/lib/x86_64-linux-gnu/libmpv.so.1.107.0
    Loading failed with message: /lib/x86_64-linux-gnu/libavfilter.so.7: undefined symbol: av_sscanf, version LIBAVUTIL_56
    Looking in classpath from {0} for {1}
    Loading failed with message: Native library (linux-x86-64/libmpv.so) not found in resource path ([file:/home/xxx/yyy/mpv.jar])
    Exception in thread "JavaFX Application Thread"
    java.lang.UnsatisfiedLinkError: Unable to load library 'mpv':
    libmpv.so: cannot open shared object file: No such file or directory
    libmpv.so: cannot open shared object file: No such file or directory
    /lib/x86_64-linux-gnu/libavfilter.so.7: undefined symbol: av_sscanf, version LIBAVUTIL_56
    Native library (linux-x86-64/libmpv.so) not found in resource path ([file:/home/xxx/yyy/mpv.jar])
        at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:302)
        at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:455)
        at com.sun.jna.Library$Handler.<init>(Library.java:192)
        at com.sun.jna.Native.load(Native.java:596)
        at hs.mediasystem.ext.mpv.MPV.<clinit>(MPV.java:12)
        at hs.mediasystem.ext.mpv.MPVPlayer.<init>(MPVPlayer.java:47)
        (... snipped 50 lines ...)
        at com.sun.glass.ui.View.handleKeyEvent(View.java:547)
        at com.sun.glass.ui.View.notifyKey(View.java:971)
        at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
        at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
        at java.base/java.lang.Thread.run(Thread.java:834)
        Suppressed: java.lang.UnsatisfiedLinkError: libmpv.so: cannot open shared object file: No such file or directory
            at com.sun.jna.Native.open(Native Method)
            at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:191)
            ... 70 more
        Suppressed: java.lang.UnsatisfiedLinkError: libmpv.so: cannot open shared object file: No such file or directory
            at com.sun.jna.Native.open(Native Method)
            at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:204)
            ... 70 more
        Suppressed: java.lang.UnsatisfiedLinkError: /lib/x86_64-linux-gnu/libavfilter.so.7: undefined symbol: av_sscanf, version LIBAVUTIL_56
            at com.sun.jna.Native.open(Native Method)
            at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:235)
            ... 70 more
        Suppressed: java.io.IOException: Native library (linux-x86-64/libmpv.so) not found in resource path ([file:/home/john/Downloads/MediaSystem/ui-plugins/mpv-plugin/mpv.jar])
            at com.sun.jna.Native.extractFromResourcePath(Native.java:1095)
            at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:276)
            ... 70 more

For some reason it cannot find some symbol av_sscanf in a dependent library. The wierd thing however is that this exact same code works in the Ubuntu installed in the VM.

Its output is:

Looking in classpath from {0} for {1}
Found library resource at {0}
Extracting library to {0}
Trying {0}
Found jnidispatch at {0}
Looking for library 'mpv'
Adding paths from jna.library.path: null
Trying libmpv.so
Loading failed with message: libmpv.so: cannot open shared object file: No such file or directory
Adding system paths: [/usr/lib/x86_64-linux-gnu, /lib/x86_64-linux-gnu, /usr/lib64, /lib64, /usr/lib, /lib]
Trying libmpv.so
Loading failed with message: libmpv.so: cannot open shared object file: No such file or directory
Looking for version variants
Trying /usr/lib/x86_64-linux-gnu/libmpv.so.1.107.0
Found library 'mpv' at /usr/lib/x86_64-linux-gnu/libmpv.so.1.107.0

I checked the versions and sizes of the libraries involved, and they seem to be all exactly the same:

john@Artec:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:   focal
john@Artec:~$ apt-cache policy libmpv1
libmpv1:
  Installed: 0.32.0-1ubuntu1
  Candidate: 0.32.0-1ubuntu1
  Version table:
 *** 0.32.0-1ubuntu1 500
        500 http://nl.archive.ubuntu.com/ubuntu focal/universe amd64 Packages
        100 /var/lib/dpkg/status
john@Artec:~$ apt-cache policy libavfilter7
libavfilter7:
  Installed: 7:4.2.2-1ubuntu1
  Candidate: 7:4.2.2-1ubuntu1
  Version table:
 *** 7:4.2.2-1ubuntu1 500
        500 http://nl.archive.ubuntu.com/ubuntu focal/universe amd64 Packages
        100 /var/lib/dpkg/status
john@Artec:~$ ll /usr/lib/x86_64-linux-gnu/libmpv.so.1.107.0 
-rw-r--r-- 1 root root 2153952 jan 31 19:11 /usr/lib/x86_64-linux-gnu/libmpv.so.1.107.0
john@Artec:~$ ll /usr/lib/x86_64-linux-gnu/libavfilter.so.7
-rw-r--r-- 1 root root 3647472 mrt  7 09:39 /usr/lib/x86_64-linux-gnu/libavfilter.so.7.57.100

Any tips on how to debug this further would be much appreciated.

More Info

This turns out to be a problem where two libraries are loaded, but requiring different versions of a shared dependent library (in this case the libavfilter library is used by both opencv/ffmpeg and libmpv, but they need a slightly different version...).

john16384
  • 7,800
  • 2
  • 30
  • 44
  • Are the cloud/local machines different architectures (e.g., ARM/AMD)? I'd take a look at environment-related things that may have caused different compilation to happen. Looking at the source code for your function might find it wrapped in a define conditional. – Daniel Widdis Jun 11 '20 at 16:35
  • Also check your version of `libavutil` (or possibly `libavutil56`) on both machines. – Daniel Widdis Jun 11 '20 at 16:52
  • @DanielWiddis the output of `uname -a` is identical, but the native install is an Intel Xeon and the VM's native hardware is an Amd Ryzen. I'm not compiling the lib's involved, they're distributed with Ubuntu. I checked the version of libavutil, it's `libavutil.so.56.31.100` and `624979` bytes in size on both machines. – john16384 Jun 11 '20 at 21:56
  • I'm getting the impression this line: `libmpv.so: cannot open shared object file: No such file or directory` might be the problem. I think it might not be able to load `libavfilter` at all and the loader just reports the first missing function as the error. `strings` shows that the symbol `av_sscanf` is part of the library. – john16384 Jun 11 '20 at 22:16
  • Yeah but I see that debug line in both systems. I do think it's likely an environment variable thing. Check `LD_LIBRARY_PATH` and if that's the same, check all the environment variables and look for differences. – Daniel Widdis Jun 11 '20 at 22:20
  • It looks like another version of `libavfilter` is already loaded before I load the `mpv` library (the project is also using ffmpeg via javacpp, and using `lsof -p ` I found out that another version of the library is unpacked somewhere and loaded). JNA then reuses this one. I checked with `strings` and that version is indeed missing the `av_sscanf` symbol. This makes things a bit trickier... not sure how I can force JNA to load different copies of the same library. – john16384 Jun 12 '20 at 22:37
  • Wow, that’s odd. Probably worth asking on JNA mailing list. I know you can unload libraries but not sure how that would work in your situation. – Daniel Widdis Jun 13 '20 at 03:55
  • I think changing the options when loading will force loading a different version. You can also [unload a single library](https://stackoverflow.com/questions/41056322/how-to-dispose-library-loaded-with-jna) -- be sure to allow a few (2-10) millisecond pause before trying to load it again. – Daniel Widdis Jun 13 '20 at 19:03
  • I opened an issue at JNA (https://github.com/java-native-access/jna/issues/1208). I don't think it can be solved with options, I played with this yesterday and it made no difference. I can't unload a library as I need both my `opencv` dependency as well as my `libmpv` dependency in the project to work (it works on Windows because the `libmpv` dll for that platform contains all dependencies)... its the Linux port that is giving me issue now :) I may be forced to split the functionality over 2 JVM's... – john16384 Jun 13 '20 at 23:40

0 Answers0