代码之家  ›  专栏  ›  技术社区  ›  Grumblesaurus

VLCJ-在64位Linux上捆绑本机VLC库

  •  2
  • Grumblesaurus  · 技术社区  · 6 年前

    背景:

    我正在用Java编写一个跨平台音频播放器。在Linux上,我以appimage的形式分发它( https://appimage.org/ ). 我使用VLC/VLCJ作为解码引擎。

    appimages的基本原则是将所有必需的库与appimages一起包含,而这些库在默认情况下不能合理地预期会与发行版一起包含。这样做的目的是不需要用户解析依赖关系和/或处理库和程序之间的版本控制差异。他们还建议对 以前的 一些Linux发行版的版本,以确认一切正常。

    默认情况下,Ubuntu 16.04和Fedora 27.16不安装libvlc。我相信这在其他发行版中很常见。因此,我想在appimage中打包libvlc库。

    问题:

    在Linux上,我无法让vlcj识别/查找 libvlc.so libvlccore.so 除非是通过配电盘安装的。

    设置:

    1. 我通过发行版安装了VLC,程序运行正常。

    2. 我抄了 libvlc.so公司 , libvlccore.so公司 ,以及其他关联库(从它们在我的分发中的默认位置到我的项目中的文件夹)。

    3. 我将该文件夹添加到本机库搜索路径(请参阅下面的代码)。

    4. 我卸载了VLC。

    5. 我试着运行我的程序。它崩溃了,错误粘贴在下面。

    注意:我对Windows使用了同样的基本方法,而且在那里工作得很好。

    简化代码:

    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 );
    

    错误消息:

    尝试在以下位置查找库: /d/programming/workspace/MusicPlayer/stage/lib/nix/vlc SLF4J:失败 加载类“org.slf4j.impl.StaticLoggerBinder”。SLF4J:默认 to no operation(NOP)logger实现SLF4J:请参阅 http://www.slf4j.org/codes.html#StaticLoggerBinder 为了进一步 细节。2018年8月5日下午22:14:32 net.joshuad.hypnos.hypnos开始 严重:类java.lang.RuntimeException:在顶部捕获到异常 催眠水平。退出。java.lang.RuntimeException:未能加载 本地图书馆。

    错误为“无法加载库'vlc':JNA本机支持 (linux-amd64/libvlc.so)在资源路径中找不到 /usr/lib/java/java/java-8-openjdk-amd64/jre/lib/resources.jar/usr/lib/java/java-8-openjdk-amd64/jre/lib/rt.jar/usr/lib/java/java/java/java-8-openjdk-amd64/jre/lib/jsse.jar/usr/lib/jsse.jar/usr/lib/java/jvm/java/java/java/java/java-lib/java-openjjjjjjr/lib/lib/java/java/java/java/lib/lib/lib/lib/resources.jar.jar/usr/usr/java/java/java/jjjjjava/openjfx/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jar/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce/sunjce-provider.jar/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar/usr/lib/jvm/java/java-8-openjdk-amd64/jre/lib/lib/ext/jacess.jar/usr/lib/lib/java/jvm/java/java/lib/jjvm/jjvm/java-8/jvm/jvm/java-8/java-8-openjvm/java-8-openjjk-8 jdk-amd64/jre/lib/ext/icedtea sound.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar/usr/lib/lib/zipfs.jar/usr/lib/jpfs/java/jvm/java-8-openjdk-amd64/jre/jre/lib/lib/ext/cldrdata.jar/usr/lib/lib/lib/cldrdata.jar/usr/lib/jvm/java/jvm/java/java/java/java/java/openjd64/jre/jre/jre/lib/lib/lib/ext/nashorn.jar/usr/shar/share/java/java/java/java/java/java-atk包装器.jar/jar/jar/jar//d////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/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-openjd64/lib/javafx mx.jar:/d/programming/workspace/MusicPlayer/stage/lib/jna-3.5.2.jar/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)”。

    所需的本机库名为“libvlc.so”和 “libvlccore.so”。

    在下面的文本中表示目录的名称 包含“libvlc.so”和“libvlccore.so”。。。

    有许多不同的方法可以指定在何处查找 本机库: 一。在应用程序代码的开头包括NativeLibrary.addSearchPath(“vlc”,“”)。 2。在应用程序代码的开头包括System.setProperty(“jna.library.path”,“”)。 三。启动应用程序时在命令行中指定-Djna.library.path=。 四。添加到系统搜索路径(并重新启动)。

    如果这仍然不起作用,那么可能需要显式地 将本机库目录添加到操作系统配置中 -例如,在Linux上,这可能意味着设置LD_LIBRARY_PATH环境变量,或将配置添加到“/etc/LD.so.conf” 文件或“/etc/ld.so.conf.d”目录。在这些选项中,设置 LD_LIBRARY_PATH是唯一不需要根目录的路径 特权。

    最后,不可能混合CPU体系结构-不可能 64位Java虚拟机可以加载32位本机 图书馆。

    日志中可能有更多信息。

    在 uk.co.caprica.vlcj.binding.LibVlcFactory.create(LibVlcFactory.java:198) 在 uk.co.caprica.vlcj.player.MediaPlayerFactory(MediaPlayerFactory.java:259) 在 uk.co.caprica.vlcj.component.AudioMediaPlayerComponent.onGetMediaPlayerFactory(AudioMediaPlayerComponent.java:177) 在 uk.co.caprica.vlcj.component.AudioMediaPlayerComponent。(AudioMediaPlayerComponent.java:109) 在 net.joshuad.hypnos.audio.VLCAudioPlayer(VLCAudioPlayer.java:75) 在net.joshuad.hypnos.audio.AudioSystem上 在net.joshuad.hypnos.hypnos.start(hypnos.java:726)上 com.sun.javafx.application.launchempl.lambda$launchApplication1$8(launchempl.java:863) 在 com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326) 在 com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295) 在java.security.AccessController.doPrivileged(本机方法)上 com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294) 在 com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 在com.sun.glass.ui.gtk.GtkApplication.\u runLoop(本地方法)上 com.sun.glass.ui.gtk.GtkApplication.lambda$null$5(GtkApplication.java:139) 运行(Thread.java:748)

    2018年8月5日22:14:32 pm NET.JouHua.ActhNOS.催眠退出信息:退出 请求:未知错误

    申请开始方法异常2018年8月5日22:14:32 PM NET.Jojua.HythNo.HypNOS退出信息:退出要求:正常

    应用程序停止方法中的异常 java.lang.reflect.InvocationTargetException位于 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)位于 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)上 com.sun.javafx.application.launchempl.launchApplicationWithArgs(launchempl.java:389) 在 com.sun.javafx.application.launchempl.launchApplication(launchempl.java:328) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)上 sun.launcher.launchelper$FXHelper.main(launchelper.java:767) 原因:java.lang.RuntimeException:应用程序启动中出现异常 方法 com.sun.javafx.application.launchempl.launchApplication1(launchempl.java:917) 在 com.sun.javafx.application.launchempl.lambda$launchApplication$1(launchempl.java:182) 在java.lang.Thread.run(Thread.java:748)上,由以下原因引起: 位于的java.lang.NullPointerException Sujuad。催眠。催眠。退出(催眠。爪哇:692)AT net.joshuad.hypnos.hypnos.start(hypnos.java:872)网址 com.sun.javafx.application.launchempl.lambda$launchApplication1$8(launchempl.java:863) 在 com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326) 在 com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295) 在java.security.AccessController.doPrivileged(本机方法)上 com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294) 在 com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 在com.sun.glass.ui.gtk.GtkApplication.\u runLoop(本地方法)上 com.sun.glass.ui.gtk.GtkApplication.lambda$null$5(GtkApplication.java:139) ... 1运行application net.joshuad.hypnos.hypnos时出现更多异常

    搜索文件夹的内容(显示libvlc.so和其他文件夹):

    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
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   Keith Russell    6 年前

    我敢打赌发行版的本机lib版本是用硬编码路径构建的,可能是绝对路径。不幸的是,编写库来要求这些并不少见——它们通常作为标志传递到./configure脚本或makefile中,或者在构建时传递到其他任何地方。唯一的解决方法是自己构建lib,或者在目标系统上的发行版lib的预期系统目录中安装并行符号链接/硬链接,以指向lib。或者在chroot下执行,但这是一个极端的选项,对您来说可能不切实际。

        2
  •  1
  •   caprica    6 年前

    我可以看到使用appimage的吸引力,但是我要做的是创建一个包含我的应用程序和vlcj并依赖于LibVLC(和jdk)的分发包(.deb或其他)。

        3
  •  0
  •   Grumblesaurus    6 年前

    我通过下载 appimage of vlc ,使用 --appimage-extract cli选项,去掉我不需要的东西,然后重新打包到我的appimage中。