shannah / jdeploy

Developer friendly desktop deployment tool
https://www.jdeploy.com
Apache License 2.0
356 stars 19 forks source link

How to fix missing classes (from dependencies) #140

Closed FDelporte closed 2 months ago

FDelporte commented 3 months ago

How to fix errors like these, which only happen with the JDeploy-installed version, not in the IDE...? Should the dependency somehow be configured to be forced to be in the installable?

Message:  Could not initialize class org.bytedeco.javacv.FFmpegFrameRecorder
Type:  NoClassDefFoundError
...
java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.javacv.FFmpegFrameRecorder
...
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.ffmpeg.global.avutil [in thread "JavaFX Application Thread"]
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at java.base/java.lang.Class.forName(Unknown Source)
    at org.bytedeco.javacpp.Loader.load(Loader.java:1289)
    at org.bytedeco.javacpp.Loader.load(Loader.java:1234)
    at org.bytedeco.javacpp.Loader.load(Loader.java:1210)
    at org.bytedeco.ffmpeg.avformat.Write_packet_Pointer_BytePointer_int.<clinit>(Write_packet_Pointer_BytePointer_int.java:21)
    at org.bytedeco.javacv.FFmpegFrameRecorder.<clinit>(FFmpegFrameRecorder.java:350)

Is related to this dependency:

implementation("org.bytedeco:javacv-platform:${Versions.javacv}")
shannah commented 2 months ago

The first thing to check is that all of the expected jar files are being included in the bundle.

Can you send a link to the release do I can take a look?

FDelporte commented 2 months ago

Release: https://github.com/codewriterbv/melodymatrix-app-releases/releases/tag/main

I tried the build generated by Gradle, and that works correctly:

$ gradle :MainApplication:shadowJar
$ java -jar MainApplication/build/libs/MelodyMatrixApp.jar
shannah commented 2 months ago

I just tried installing and running it on Windows 11, and it seemed to launch ok.

How are you running it when you get that stack trace? Are you on the command-line, or are you launching it from the dock/start menu/desktop link/etc..?

FDelporte commented 2 months ago

Yes launches ok, but the error is in piano view when starting a video recording. Can make a video tomorrow.

shannah commented 2 months ago

Thanks. That gave me a clue.

I took a look at the bundled jar, and it appears to only include opencv native libs for linux. If you're bundling for all platforms, you'll need to bundle all of the native libs.

This thread shows a gradle option to specify which platforms you bundle for.

https://stackoverflow.com/a/76925273/2935174

plugins {
  id 'org.bytedeco.gradle-javacpp-platform' version "1.5.9"
}

// We can set this on the command line too this way: -PjavacppPlatform=linux-x86_64,macosx-x86_64,windows-x86_64,etc
ext {
    javacppPlatform = 'linux-x86_64,macosx-x86_64,windows-x86_64,etc' // defaults to Loader.getPlatform()
}
steve@SteveDell MINGW64 ~/.jdeploy/gh-packages/9394f3651a537d4e802cfccd54950639.MelodyMatrix/0.0.0-main/73b616b6431e0a638fdbeedf1d75748dc4a57c94/jdeploy-bundle
$ jar tvf MelodyMatrixApp.jar | grep -i avutil
...
     0 Wed Jul 31 14:07:36 PDT 2024 META-INF/native-image/linux-x86_64/jniavutil/
 18402 Fri Jan 26 16:47:24 PST 2024 META-INF/native-image/linux-x86_64/jniavutil/reflect-config.json
 18402 Fri Jan 26 16:47:24 PST 2024 META-INF/native-image/linux-x86_64/jniavutil/jni-config.json
   224 Fri Jan 26 16:47:36 PST 2024 META-INF/native-image/linux-x86_64/jniavutil/resource-config.json
5871920 Fri Jan 26 16:47:36 PST 2024 org/bytedeco/ffmpeg/linux-x86_64/libavutil.so.58
1272720 Fri Jan 26 16:47:36 PST 2024 org/bytedeco/ffmpeg/linux-x86_64/libjniavutil.so

Unfortunately this means that your app bundle size will grow larger since it needs to include mac, windows, and linux and all architectures.

I added experimental support for adding install-time maven dependencies some time ago (so that it downloads from maven central at runtime), but that still needs a bit of work and more testing before I recommend it.

FDelporte commented 2 months ago

Thanks again @shannah !

Adding this seems to have solved the issue on my Mac ARM machine, still need to test others, but looks good and it seems to me the size didn't change much...


plugins {
    ...
    // Some native libraries are required, but not all, to prevent errors
    //  - ktmidi -> should not include Android
    //    https://github.com/atsushieno/ktmidi/issues/79
    //  - javacv -> needs all supported platforms, otherwise only contains Linux
    //    https://github.com/shannah/jdeploy/issues/140#issuecomment-2261492683
    //    https://stackoverflow.com/questions/76908209/how-to-gradle-load-javacv-binaries-only-for-current-platform/76925273
    // This plugin replaces the references to all those javacpp platforms with whatever required
    // only for the platform.
    // https://github.com/bytedeco/gradle-javacpp
    id("org.bytedeco.gradle-javacpp-platform") version "1.5.10"
}

// Defines the platforms
extra["javacppPlatform"] = "linux-x86_64,linux-arm64,macosx-x86_64,macosx-arm64,windows-x86_64"
FDelporte commented 2 months ago

I have to add: I love the idea of "adding install-time maven dependencies." it makes total sense to reduce the total size and wasted energy and storage space.