beryx/badass-jlink-plugin

java.lang.LayerInstantiationException and Kotlin

Closed this issue · 4 comments

TX256 commented

Hi. I'm attempting to build a quite simple Kotlin/JavaFx project with badass.

I've gotten everything else to (seemingly) work, but when I run the jpackage-task, and then attempt to run the generated exe-file on Windows, I get the following error:

java.lang.LayerInstantiationException: Package kotlin.io in both module myapp.merged.module and module kotlin.stdlib

If I try to run it again subsequently, I get different, but related messages, like:

java.lang.LayerInstantiationException: Package kotlin.reflect in both module kotlin.stdlib and module myapp.merged.module

All related to Kotlin.

My specs are:

  • Windows 10
  • Eclipse OpenJ9 15
  • Gradle 6.7
  • Kotlin 1.4.21

Any ideas what might be wrong?

It seems that the Kotlin library is both included in the merged module and available as a proper module on the module path. But I can't say why this is happening without seeing the code. Can you put your project (or a simplified version that still allows reproducing the issue) on GitHub?

TX256 commented

OK, I created a simple test project with the same dependencies as I have in my main app.

It fails similarly if I have the same dependencies in Gradle, and the corresponding modules specified for them in module-info.java.

I also tried to comment them out one by one, and I think at least JNA is a "hostile" library related to this issue... but it seems there is another one too, since from quick test, I couldn't get my main project to work with only JNA removed.

Just run the jpackage-task, and then execute "app-test.exe"... and it should fail with java.lang.LayerInstantiationException. However, if you comment out all the gradle dependencies and the associated module specifications, "Hello world!" will be printed.

When running gradle with the -i flag, the output contains:

modularJars: [kotlin-stdlib-1.4.21.jar, controlsfx-11.0.3.jar]
nonModularJars: [kotlin-stdlib-common-1.4.21.jar, ...]

Your application depends on kotlin-stdlib and kotlin-stdlib-common, but only kotlin-stdlib is a modular jar. That's why kotlin-stdlib-common gets included in the merged module. Since kotlin-stdlib and kotlin-stdlib-common share several packages, you get the LayerInstantiationException. The solution is to also include kotlin-stdlib into the merged module. To do this replace the line:

forceMerge "gson"

with

forceMerge "gson", "kotlin"

For this simple test project, you also need to put imageOptions += ['--win-console'] in the jpackage block. You don't need it for your real JavaFX application, but it can be useful for troubleshooting.

TX256 commented

Thank you for the explanation and solution, it works now.