sbt / sbt-native-packager

sbt Native Packager
https://sbt-native-packager.readthedocs.io/en/stable/
BSD 2-Clause "Simplified" License
1.6k stars 441 forks source link

JDKPackager output error #727

Open ekis opened 8 years ago

ekis commented 8 years ago

I am trying to build an executable, bundled JAR with JDK Packager plugin on Windows and Inno Setup - and while the packager plugin itself produces an installable resource and I cannot see any errors during the packaging, after installation I am left with an unusable application and little hints as to what is going on and why.

I have the full synopsis of the problem here but in a nutshell, the packaged exe throws some hard-to-reason about errors and there is no error log whatsoever (at least I cannot find any). I've been bashing my head with this for two days and cannot figure out what is going on - I've tried to go the Wix way but that seems even crazier: I could not get even the My First Packaged Tutorial to build correctly.

Can we do anything on sbt-native-packager side to make these (as detailed on SO link) errors a little bit more explicit or is it all out of our hands?

Lastly, I understand this may not be the best place to post such issues but I would really appreciate if someone could take a look at the issue and/or provide some hints where to go next as this lack of sensible logging is frustrating. I've went through JDK Packager documentation, all tutorials on sbt-native-packager, Oracle JavaPackager docs (such as they are) and ant javafx reference - but am no closer to understanding what is going on, why is this happening and what have I done wrong.

If there is anything I can post to help move this forward, please don't hesitate to ask.

ekis commented 8 years ago

My investigations on this continue, here is the summary of current efforts.

  1. I found a bug report in JDK 8u60 claiming this particular version packager produces a Windows installer that completes orderly but the application crashes after execution. I tried downgrading to 8u45 and upgrading 8u65 - aside from a slightly different error dialog in 8u45, nothing materially changed; the report was the same: "Error invoking method". It might be useful, however, to include this bug report in documentation - it might save some frustration.
  2. As suggested by @muuki88 here, there are native startscript scripts provided by sbt-native-packager. I didn't know exactly to what this referred so I had assumed I should be trying the batch script that can be found in %APPDIR%\app\bin. Observations:
    • the script does not work out of the box. It throws the following two errors:
      • (Error 1) The system cannot find the file c:\Program Files\bootstrapCli\app\bin\\\..\BOOTSTRAPCLI_config.txt.
      • (Error 2) A Java JDK is not installed or can't be found.
    • Error 1 was easily fixed(?) by pointing at the proper configuration file named bootstrapCli.cfg in %APPDIR%\app\bin directory, so I changed line 21 in batch file to point to correct file. The error did disappear but this seems like a bug, though I don't know if it's sbt-native-packager or invoked jdkpackager responsibility to create the batch file; I assume the former? If that is the case, should we log a bug or at least update the docs?
    • Error 2 seems very unexpected. My idea of "bundled application" would be to bundle the whole JDK in runtime application directory but it seems this directory contains a certain subset of JDK files, probably the bare minimum needed for generated entry point .exe file to use the Invocation API, get the jvm.dll and fire up the JVM. The generated .exe file then uses the generated bootstrapCli.cfg file to pass various options to JVM. However, if that is the case, then what is the purpose of the batch file I had invoked? The batch file seems to rely on JDK being installed which is contradictory to the idea of bundled application - so this is quite confusing and unexpected.
  3. I also tried hack....ehm, altering various options in bootstrapCli.cfg and then running the generated .exe file. Observations:
    • I altered app.mainjar property value to point to a "non-launcher" bootstrap JAR. It now essentially throws ClassNotFoundException on defined main class which is relatively expected as the JAR's manifest file contains no Class-Path element.
      • I manually injected the missing Class-Path element using the boostrap launcher JAR. Ineffectively, as it throws the familiar Error invoking method dialog (same as running the launcher JAR) followed by Failed to launch JVM.
    • I reverted back the manifest files to "stock" configuration and added lib\ to every JAR specified in generated bootstrapCli.cfg. That also prevented the ClassNotFoundException but was ultimately ineffective as it threw the Error invoking method dialog after path manipulation.

After this it became clear it is inadvisable to touch the generated .cfg file so I reverted everything to stock and just wanted to see if the JVM is actually loaded. As it turns out, it is - using ProcExp and ProcMon I was able to prove the jvm.dll is successfully found and loaded. So why is JVM failing to launch is still a mystery I don't know how to investigate any more.

Additional question is - what is the actual purpose of app.classpath property value in generated .cfg? I observed this file is being read by generated .exe but why do we include the full classpath? It is already included in launcher JAR's manifest. Does the JVM care? It does but only if passed a single class - since we're always(?) passing in JAR files, the classpath should be read from the JAR file (MANIFEST.MF).

Summary: the problem is still unsolved but the whole process is very opaque and hard to reason about. We should improve the documentation to be a little bit more specific about the components and process involved - such as it is, the debugging process amounts to box rattling and observing the effects. Can we do better?

metasim commented 8 years ago

@ekis Are you using sbt-assembly?

ekis commented 8 years ago

@metasim No, I am not - perhaps I was unclear: I had never used it not together with sbt-native-packager just had the definition in plugins.sbt. I had removed sbt-assembly altogether (together with definition) but that didn't help.

metasim commented 8 years ago

@ekis Does sbt-dependency-tree or the Ivy reports indicate any evictions?

muuki88 commented 8 years ago

@ekis Thanks for the rich explanation. So in summary the generated exe is corrupted in many ways. So we have to find out who is responsible for corrupting the exe. I have no experience with windows packaging so this is just a few more hints to follow

metasim commented 8 years ago

@ekis To echo off of @muuki88's comments, if you're able to manually edit the generated build.xml file and use Ant directly to get things to work, and let us know what you had to change, it would help us see if there's some check missing in the plugin.

I'm also not sure what this .cfg file is... maybe something generated by javapackager on windows? At any rate, the build.xml file is the authoritative definition from the plugin's standpoint. Anything downstream from that is javapackager land.