Java snap not working

Hi, does anybody know how to build snaps? Anyone know what might be wrong with my snapcraft.yaml file? I was trying to follow https://snapcraft.io/blog/building-a-java-snap-by-example as far as possible.

This is what happens:

/snap/bin/tuxfight 
/snap/tuxfight/x1/bin/desktop-launch: line 611: /snap/tuxfight/x1/bin/launcher: No such file or directory
name: tuxfight
adopt-info: tuxfight
summary: TuxFight
description: Battle it out with other Tuxes! Fight to dominate Antarctica and be the supreme penguin. You can choose to be Ice Tux, Fish Tux, Tech Tux and Fire Tux. Each of them has different abilities and powers. Control the players using a keyboard or the on-screen controls. There is even a split screen mode so you can play with another person at the same time, using on-screen controls at opposite ends of your touchscreen if you don't have a keyboard!
base: core18

grade: stable
confinement: strict

apps:
  tuxfight:
    command: desktop-launch $SNAP/bin/launcher
    plugs:
    - network
    - network-bind
    - opengl
    - home
    - joystick
    - pulseaudio
    - desktop
    - wayland
    - x11
    - desktop-legacy
    - unity7
    environment:
      XDG_DATA_HOME: "$SNAP/usr/share"
      JAVA_HOME: "$SNAP/usr/lib/jvm/java-11-openjdk-amd64/jre/"
      PATH: "$SNAP/bin:$PATH:$SNAP/usr/lib/jvm/java-11-openjdk-amd64/jre/bin"
      GVFS_MOUNTABLE_DIR: "$SNAP/usr/share/gvfs/mounts"
      GVFS_MONITOR_DIR: "$SNAP/usr/share/gvfs/remote-volume-monitors"
      LD_LIBRARY_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio"

parts:
  tuxfight:
    after: [desktop-gtk2]
    plugin: nil
    override-build: |
      wget -O $SNAPCRAFT_PART_INSTALL/TuxFight-0.0.1.jar http://192.168.1.53/TuxFight-0.0.1.jar
      snapcraftctl set-version "0.0.1"
    build-packages:
      - wget
    stage-packages:
      - openjdk-11-jre
      - ca-certificates
      - ca-certificates-java
      - libpulse0
      - libpulsedsp
      - libxxf86vm1
      - libgl1-mesa-dri
      - libglu1-mesa
      - libgl1-mesa-glx
      - libgles2-mesa
      - x11-xserver-utils
    prime:
        - -usr/lib/jvm/java-*/lib/security/cacerts
        - -usr/lib/jvm/java-*/jre/lib/security/cacerts
  launcher:
    plugin: dump
    source: .
    organize:
      'launcher': 'bin/'
      'padsp': 'bin/'
      'sensible-browser': 'bin/'
      'usr/lib/*/gvfs/*.so': 'usr/lib'
      'usr/bin/xprop': 'usr/bin/xprop.disabled'
  desktop-gtk2:
    build-packages:
      - build-essential
      - libgtk2.0-dev
    make-parameters:
      - FLAVOR=gtk2
    plugin: make
    source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
    source-subdir: gtk
    stage-packages:
      - libxkbcommon0
      - ttf-ubuntu-font-family
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-standard
      - shared-mime-info
      - libgtk2.0-0
      - libgdk-pixbuf2.0-0
      - libglib2.0-bin
      - libgtk2.0-bin
      - unity-gtk2-module
      - locales-all
      - libappindicator1
      - xdg-user-dirs
      - ibus-gtk
      - libibus-1.0-5

does this file exist in your snap?

It doesn’t. How is it supposed to be created? In Shattered Pixel Dungeon they do this:

  launcher:
    plugin: dump
    source: snap/local
    organize:
      'padsp': 'bin/'
      'sensible-browser': 'bin/'
      'usr/lib/*/gvfs/*.so': 'usr/lib'
      'usr/bin/xprop': 'usr/bin/xprop.disabled'

But the snap/local caused an error on my machine and I read in some other forum that we could replace it with “.”. How do I get snapcraft to create the launcher to launch the JVM and open my jar?

by you :wink:

the dump plugin copies existing files around. did you create a snap/local/ directory with all these files in it in your source tree ?

Here’s what I did instead I just called the JVM directly:

name: tuxfight
adopt-info: tuxfight
summary: TuxFight
description: Battle it out with other Tuxes! Fight to dominate Antarctica and be the supreme penguin. You can choose to be Ice Tux, Fish Tux, Tech Tux and Fire Tux. Each of them has different abilities and powers. Control the players using a keyboard or the on-screen controls. There is even a split screen mode so you can play with another person at the same time, using on-screen controls at opposite ends of your touchscreen if you don't have a keyboard!
base: core18
icon: snap/gui/tuxfight.png

grade: stable
confinement: classic

apps:
  tuxfight:
    command: desktop-launch $SNAP/usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar $SNAP/bin/TuxFight-1.0.4.jar
    plugs:
    - network
    - network-bind
    - opengl
    - home
    - joystick
    - pulseaudio
    - desktop
    - wayland
    - x11
    - desktop-legacy
    - unity7
    environment:
      XDG_DATA_HOME: "$SNAP/usr/share"
      JAVA_HOME: "$SNAP/usr/lib/jvm/java-11-openjdk-amd64"
      PATH: "$SNAP/bin:$PATH:$SNAP/usr/lib/jvm/java-11-openjdk-amd64/bin"
      GVFS_MOUNTABLE_DIR: "$SNAP/usr/share/gvfs/mounts"
      GVFS_MONITOR_DIR: "$SNAP/usr/share/gvfs/remote-volume-monitors"
      LD_LIBRARY_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio"

parts:
  tuxfight:
    after: [desktop-gtk2]
    plugin: nil
    override-build: |
      mkdir $SNAPCRAFT_PART_INSTALL/bin
      wget -O $SNAPCRAFT_PART_INSTALL/bin/TuxFight-1.0.4.jar http://192.168.1.53/TuxFight-1.0.4.jar
      snapcraftctl set-version "1.0.4"
    build-packages:
      - wget
    stage-packages:
      - openjdk-11-jre
      - ca-certificates
      - ca-certificates-java
      - libpulse0
      - libpulsedsp
      - libxxf86vm1
      - libgl1-mesa-dri
      - libglu1-mesa
      - libgl1-mesa-glx
      - libgles2-mesa
      - x11-xserver-utils
    prime:
        - -usr/lib/jvm/java-*/lib/security/cacerts
        - -usr/lib/jvm/java-*/jre/lib/security/cacerts
  launcher:
    plugin: dump
    source: .
    organize:
      'launcher': 'bin/'
      'padsp': 'bin/'
      'sensible-browser': 'bin/'
      'usr/lib/*/gvfs/*.so': 'usr/lib'
      'usr/bin/xprop': 'usr/bin/xprop.disabled'
  desktop-gtk2:
    build-packages:
      - build-essential
      - libgtk2.0-dev
    make-parameters:
      - FLAVOR=gtk2
    plugin: make
    source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
    source-subdir: gtk
    stage-packages:
      - libxkbcommon0
      - ttf-ubuntu-font-family
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-standard
      - shared-mime-info
      - libgtk2.0-0
      - libgdk-pixbuf2.0-0
      - libglib2.0-bin
      - libgtk2.0-bin
      - unity-gtk2-module
      - locales-all
      - libappindicator1
      - xdg-user-dirs
      - ibus-gtk
      - libibus-1.0-5

Now it’s failing to load opengl despite the relevant plug being stated and the DRI files clearly being there in the installed snap:

[ALSOFT] (EE) Failed to set real-time priority for thread: Operacio ne permesatas (1)
[ALSOFT] (EE) Failed to set real-time priority for thread: Operacio ne permesatas (1)
libGL error: MESA-LOADER: failed to open iris: libLLVM-10.so.1: ne eblas malfermi komunan objektdosieron: Dosiero aŭ dosierujo ne ekzistas (search paths /snap/tuxfight/x1/usr/lib/x86_64-linux-gnu/dri, suffix _dri)
libGL error: failed to load driver: iris
libGL error: MESA-LOADER: failed to open iris: libLLVM-10.so.1: ne eblas malfermi komunan objektdosieron: Dosiero aŭ dosierujo ne ekzistas (search paths /snap/tuxfight/x1/usr/lib/x86_64-linux-gnu/dri, suffix _dri)
libGL error: failed to load driver: iris
libGL error: MESA-LOADER: failed to open swrast: libLLVM-10.so.1: ne eblas malfermi komunan objektdosieron: Dosiero aŭ dosierujo ne ekzistas (search paths /snap/tuxfight/x1/usr/lib/x86_64-linux-gnu/dri, suffix _dri)
libGL error: failed to load driver: swrast
[LWJGL] GLFW_VERSION_UNAVAILABLE error
        Description : GLX: Failed to create context: BadValue (integer parameter out of range for operation)
        Stacktrace  :
                org.lwjgl.glfw.GLFW.nglfwCreateWindow(GLFW.java:2024)
                org.lwjgl.glfw.GLFW.glfwCreateWindow(GLFW.java:2197)
                com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createGlfwWindow(Lwjgl3Application.java:519)
                com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:457)
                com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:443)
                com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:158)
                com.customautosys.tuxfight.desktop.Lwjgl3Launcher.createApplication(Lwjgl3Launcher.java:21)
                com.customautosys.tuxfight.desktop.Lwjgl3Launcher.main(Lwjgl3Launcher.java:14)
Exception in thread "main" com.badlogic.gdx.utils.GdxRuntimeException: Couldn't create window
        at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createGlfwWindow(Lwjgl3Application.java:522)
        at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:457)
        at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:443)
        at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:158)
        at com.customautosys.tuxfight.desktop.Lwjgl3Launcher.createApplication(Lwjgl3Launcher.java:21)
        at com.customautosys.tuxfight.desktop.Lwjgl3Launcher.main(Lwjgl3Launcher.java:14)

if you do not use a desktop extension and instead pick to use the old desktop-helpers, it is up to you to ship all depending libraries (i guess libllvm10 in this case) in your stage-packages … i’d rather go with using the gnome-3-38-2004 extension instead if you can …

So I’ve just tried this:

name: tuxfight
adopt-info: tuxfight
summary: TuxFight
description: |
  Battle it out with other Tuxes! Fight to dominate Antarctica and be the supreme penguin. You can choose to be Ice Tux, Fish Tux, Tech Tux and Fire Tux. Each of them has different abilities and powers. Control the players using a keyboard or the on-screen controls. There is even a split screen mode so you can play with another person at the same time, using on-screen controls at opposite ends of your touchscreen if you don't have a keyboard!
  You will need to run "snap connect tuxfight:dot-prefs; snap connect tuxfight:dev-shm" for the app to run.
base: core18
icon: snap/gui/tuxfight.png

grade: stable
confinement: strict

plugs:
  dot-prefs:
    interface: personal-files
    write:
    - $HOME/.prefs
  dev-shm:
    interface: system-files
    write:
    - /dev/shm

apps:
  tuxfight:
    extensions:
      - gnome-3-28
    command: desktop-launch $SNAP/usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar $SNAP/bin/TuxFight-1.0.4.jar
    plugs:
    - network
    - network-bind
    - opengl
    - home
    - joystick
    - pulseaudio
    - desktop
    - wayland
    - x11
    - desktop-legacy
    - unity7
    - dot-prefs
    - dev-shm
    environment:
      XDG_DATA_HOME: "$SNAP/usr/share"
      JAVA_HOME: "$SNAP/usr/lib/jvm/java-11-openjdk-amd64"
      PATH: "$SNAP/bin:$PATH:$SNAP/usr/lib/jvm/java-11-openjdk-amd64/bin"
      GVFS_MOUNTABLE_DIR: "$SNAP/usr/share/gvfs/mounts"
      GVFS_MONITOR_DIR: "$SNAP/usr/share/gvfs/remote-volume-monitors"
      LD_LIBRARY_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa-gl:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/xorg:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio/"
      LIBGL_DRIVERS_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri"

parts:
  tuxfight:
    plugin: nil
    override-build: |
      mkdir $SNAPCRAFT_PART_INSTALL/bin
      wget -O $SNAPCRAFT_PART_INSTALL/bin/TuxFight-1.0.4.jar http://192.168.1.53/TuxFight-1.0.4.jar
      snapcraftctl set-version "1.0.4"
    build-packages:
      - wget
    stage-packages:
      - openjdk-11-jre
      - ca-certificates
      - ca-certificates-java
      - libpulse0
      - libpulsedsp
      - libxxf86vm1
      - libgl1-mesa-dri
      - libglu1-mesa
      - libgl1-mesa-glx
      - libgles2-mesa
      - x11-xserver-utils
      - libatk-bridge2.0-0
    prime:
        - -usr/lib/jvm/java-*/lib/security/cacerts
        - -usr/lib/jvm/java-*/jre/lib/security/cacerts

Now I’m getting frequent segfaults on startup and this is what happens immediately before.

[ALSOFT] (EE) Failed to set real-time priority for thread: Operation not permitted (1)
ALSA lib conf.c:3916:(snd_config_update_r) Cannot access file /usr/share/alsa/alsa.conf
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM default
jan 25, 2022 9:08:49 PTM me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
INFO: LOCATING |> In progress...
jan 25, 2022 9:08:49 PTM me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
INFO: INITIALIZING |> In progress...
jan 25, 2022 9:08:49 PTM me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
INFO: INITIALIZED |> In progress...
initialize on Thread[AWT-EventQueue-0,6,main] with library path /tmp/hsperfdata_customautosys/jcef-bundle

I’m also constantly getting this error which I suspect is something to do with permissions / certificates / dependencies or some other nonsense which I don’t get from my deb file:

I will give up on fixing further and just deploy the snap as is since it is so hard to get it working. Why is it so incredibly hard to make a snap? When I use jpackage to generate a deb it is completely fuss-free and just takes 1 command. I have to do so many things to create a snap and the worse thing is, it doesn’t work and the process is so opaque and it’s hard to chase down the errors because these aren’t errors in my code. There should be a simple command to just create a snap with default options from a jar, or just convert a deb into a snap based on the dependencies of the deb. I’m sure that must be a common use case. I don’t understand why Canonical is making it so difficult to deploy our apps and this is bad for linux desktop adoption. Deployment on Google Play is so much easier.

you should use snapcraft-preload (like snappy-debug suggested to you) so the /dev/shm path of your app gets changed/overridden instead of trying to open up /dev/shm via a system-files interface …

i’m not a java programmer, so i can not really judge, but i always find creating snaps a lot easier than creating any type of deb (one single file to maintain vs a plethora of esoteric files in the debian/ dir) if you do not have a tool where people put years of work into to generate all this for you with a single command like jpackage …

perhaps in a few years the jpackage maintainers will also support snap generation the same way though … until then it is indeed not different from manually packaging a deb and having to maintain 20 files in the debian/ dir that you have understand …

snap is a way to get your app to run in all possible linux distros out there in a secured way, to do this the setup is indeed different from everything that has been around before and it will not yet cover all use-cases out of the box or in a way where you do not need to understand the surrounding setup simply because such a system has not existed before …

I tried to use https://github.com/sergiusens/snapcraft-preload and I got this:

[0203/135419.341283:ERROR:platform_shared_memory_region_posix.cc(250)] Creating shared memory in /dev/shm/.org.chromium.Chromium.vlXjoA failed: Permission denied (13) Trace/breakpoint trap (core dumped)

I followed the instructions for snapcraft-preload exactly. What am I supposed to do?

Finally after a lot of trial and error, I got it working!

Here’s the final snapcraft.yaml:

name: tuxfight
adopt-info: tuxfight
summary: TuxFight
description: Battle it out with other Tuxes! Fight to dominate Antarctica and be the supreme penguin. You can choose to be Ice Tux, Fish Tux, Tech Tux and Fire Tux. Each of them has different abilities and powers. Control the players using a keyboard or the on-screen controls. There is even a split screen mode so you can play with another person at the same time, using on-screen controls at opposite ends of your touchscreen if you don't have a keyboard!
base: core18
icon: snap/gui/tuxfight.png

grade: stable
confinement: strict

apps:
  tuxfight:
    extensions:
      - gnome-3-28
    command: desktop-launch $SNAP/bin/snapcraft-preload $SNAP/bin/launcher
    plugs:
    - audio-playback
    - network
    - network-bind
    - opengl
    - home
    - joystick
    - desktop
    - wayland
    - x11
    - desktop-legacy
    - unity7
    environment:
      XDG_DATA_HOME: "$SNAP/usr/share"
      JAVA_HOME: "$SNAP/usr/lib/jvm/java-17-openjdk-amd64"
      PATH: "$SNAP/bin:$PATH:$SNAP/usr/lib/jvm/java-17-openjdk-amd64/bin"
      GVFS_MOUNTABLE_DIR: "$SNAP/usr/share/gvfs/mounts"
      GVFS_MONITOR_DIR: "$SNAP/usr/share/gvfs/remote-volume-monitors"
      LD_LIBRARY_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa-gl:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/xorg:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio/"
      LIBGL_DRIVERS_PATH: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri"

parts:
  snapcraft-preload:
    source: https://github.com/sergiusens/snapcraft-preload.git
    plugin: cmake
    build-packages:
      - on amd64:
          - gcc-multilib
          - g++-multilib
  copy-jar:
    plugin: dump
    source: snap/local
    stage:
      - bin/TuxFight-1.0.4.jar
      - etc/ssl/certs/java/cacerts
    organize:
      TuxFight-1.0.4.jar: bin/TuxFight-1.0.4.jar
      cacerts: etc/ssl/certs/java/cacerts
  tuxfight:
    plugin: nil
    override-build: |
      mkdir -p $SNAPCRAFT_PART_INSTALL/bin
      echo '$SNAP/usr/lib/jvm/java-17-openjdk-amd64/bin/java -Djavax.net.ssl.trustStore=$SNAP/etc/ssl/certs/java/cacerts -jar $SNAP/bin/TuxFight-1.0.4.jar' > $SNAPCRAFT_PART_INSTALL/bin/launcher
      chmod +x $SNAPCRAFT_PART_INSTALL/bin/launcher
      snapcraftctl set-version "1.0.4"
    stage-packages:
      - openjdk-17-jre
      - ca-certificates
      - ca-certificates-java
      - libpulse0
      - libpulsedsp
      - libxxf86vm1
      - libgl1-mesa-dri
      - libglu1-mesa
      - libgl1-mesa-glx
      - libgles2-mesa
      - x11-xserver-utils
      - libatk-bridge2.0-0
      - libasound2
    prime:
      - -usr/lib/jvm/java-*/lib/security/cacerts
      - -usr/lib/jvm/java-*/jre/lib/security/cacerts

I had to copy in the cacerts file from my /etc/ssl/certs/java/cacerts otherwise it wouldn’t work.

Also had to do this for Chromium:

CefAppBuilder builder=new CefAppBuilder();
...
builder.addJcefArgs("--disable-dev-shm-usage");

As well as this:

Lwjgl3ApplicationConfiguration configuration = new Lwjgl3ApplicationConfiguration();
...
configuration.setPreferencesConfig(System.getenv("HOME")+"/.prefs",Files.FileType.External);

If anyone needs help with a libgdx / JCEF snap in the future, I’m happy to help!

2 Likes