在使用 jpackage 创建的已安装可执行文件启动时出现 ClassNotFoundException。

huangapple go评论75阅读模式
英文:

ClassNotFoundException when launching an installed executable created with jpackage

问题

以下是翻译好的内容:


生成 MSI 安装程序的过程如下:

  1. 运行 mvn install 以生成 Example-1.0-SNAPSHOT-jar-with-dependencies.jar
  2. 运行 windows-executable.bat 以生成 Example-1.0.0.msi
  3. 安装 Example-1.0.0.msi
  4. 前往安装目录,打开终端,运行 Example-1.0.0.exe 以查看阻止应用程序启动的任何错误。

此 POM 文件(已删除不相关部分)在 mvn install 期间用于生成 Example-1.0-SNAPSHOT-jar-with-dependencies.jar

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.Valkryst</groupId>
    <artifactId>Example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 其他属性,依赖项和构建配置已省略 -->
</project>

此脚本使用 jpackage 生成 MSI 安装程序。

mkdir temp
mklink "%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar" "%~dp0..\..\target\Example-1.0-SNAPSHOT-jar-with-dependencies.jar"

"C:\Program Files\Java\jdk-14\bin\jpackage.exe" ^
--type msi ^
--app-version "1.0.0" ^
--copyright "Valkryst, 2020" ^
--name "Example" ^
--vendor "Valkryst" ^
--verbose ^
--icon "%~dp0..\..\res\icon\icon.ico" ^
--input "%~dp0temp" ^
--java-options "-Djdk.module.illegalAccess=permit" ^
--main-class "com.valkryst.Example.Driver" ^
--main-jar "Example-1.0-SNAPSHOT-jar-with-dependencies.jar" ^
--win-dir-chooser ^
--win-shortcut ^
--win-console

del "%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar"
rmdir "%~dp0temp"
pause

这是步骤#4的输出。

PS C:\Program Files\Example> .\Example.exe
Error: Could not find or load main class com.valkryst.Example.Driver
Caused by: java.lang.ClassNotFoundException: com.valkryst.Example.Driver
英文:

My process for generating the MSI installer is as follows.

  1. Run mvn install to generate Example-1.0-SNAPSHOT-jar-with-dependencies.jar.
  2. Run windows-executable.bat to generate Example-1.0.0.msi.
  3. Install Example-1.0.0.msi.
  4. Go to the install directory, open a terminal, and run Example-1.0.0.exe to see any errors preventing the application from launching.

This POM file (irrelevant sections removed) is used during mvn install to generate Example-1.0-SNAPSHOT-jar-with-dependencies.jar.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;com.github.Valkryst&lt;/groupId&gt;
    &lt;artifactId&gt;Example&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

    &lt;properties&gt;
        &lt;maven.compiler.source&gt;11&lt;/maven.compiler.source&gt;
        &lt;maven.compiler.target&gt;11&lt;/maven.compiler.target&gt;
        &lt;maven.compiler.release&gt;11&lt;/maven.compiler.release&gt;
        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;
    &lt;/properties&gt;

    &lt;repositories&gt;
        &lt;!-- REMOVED --&gt;
    &lt;/repositories&gt;

    &lt;dependencies&gt;
        &lt;!-- REMOVED --&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;sourceDirectory&gt;src&lt;/sourceDirectory&gt;
        &lt;resources&gt;
            &lt;resource&gt;
                &lt;directory&gt;res&lt;/directory&gt;
            &lt;/resource&gt;
        &lt;/resources&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;compilerArgs&gt;
                        &lt;arg&gt;--add-exports=java.desktop/sun.java2d.d3d=ALL-UNNAMED&lt;/arg&gt;
                        &lt;arg&gt;--add-exports=java.desktop/sun.java2d.pipe.hw=ALL-UNNAMED&lt;/arg&gt;
                        &lt;arg&gt;--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED&lt;/arg&gt;
                        &lt;arg&gt;--add-exports=java.desktop/sun.java2d=ALL-UNNAMED&lt;/arg&gt;
                    &lt;/compilerArgs&gt;
                    &lt;fork&gt;true&lt;/fork&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;

            &lt;!-- Used, during the test phase of the build, to run the unit tests --&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.surefire&lt;/groupId&gt;
                &lt;artifactId&gt;surefire&lt;/artifactId&gt;
                &lt;version&gt;2.21.0&lt;/version&gt;
            &lt;/plugin&gt;

            &lt;!-- Used to include all of the dependencies in the packaged Jar file --&gt;
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;archive&gt;
                        &lt;manifest&gt;
                            &lt;mainClass&gt;com.valkryst.Example.Driver&lt;/mainClass&gt;
                        &lt;/manifest&gt;
                    &lt;/archive&gt;
                    &lt;descriptorRefs&gt;
                        &lt;descriptorRef&gt;jar-with-dependencies&lt;/descriptorRef&gt;
                    &lt;/descriptorRefs&gt;
                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;make-assembly&lt;/id&gt; &lt;!-- this is used for inheritance merges --&gt;
                        &lt;phase&gt;package&lt;/phase&gt; &lt;!-- bind to the packaging phase --&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;single&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;

This script uses jpackage to generate the MSI installer.

mkdir temp
mklink &quot;%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot; &quot;%~dp0..\..\target\Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot;

&quot;C:\Program Files\Java\jdk-14\bin\jpackage.exe&quot; ^
--type msi ^
--app-version &quot;1.0.0&quot; ^
--copyright &quot;Valkryst, 2020&quot; ^
--name &quot;Example&quot; ^
--vendor &quot;Valkryst&quot; ^
--verbose ^
--icon &quot;%~dp0..\..\res\icon\icon.ico&quot; ^
--input &quot;%~dp0temp&quot; ^
--java-options &quot;-Djdk.module.illegalAccess=permit&quot; ^
--main-class &quot;com.valkryst.Example.Driver&quot; ^
--main-jar &quot;Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot; ^
--win-dir-chooser ^
--win-shortcut ^
--win-console

del &quot;%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot;
rmdir &quot;%~dp0temp
pause

This is the output from step #4.

PS C:\Program Files\Example&gt; .\Example.exe
Error: Could not find or load main class com.valkryst.Example.Driver
Caused by: java.lang.ClassNotFoundException: com.valkryst.Example.Driver

答案1

得分: 0

经进一步调查,看起来 jpackage 实用程序不支持符号链接。它未将 `Example-1.0-SNAPSHOT-jar-with-dependencies.jar` 打包到可执行文件中,因此安装的 `Example-1.0.0.exe` 无法加载主 `Driver` 类,因为它在安装目录中不存在。

mkdir temp
copy "%~dp0..\..\target\Example-1.0-SNAPSHOT-jar-with-dependencies.jar" "%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar"

"C:\Program Files\Java\jdk-14\bin\jpackage.exe" ^
--type msi ^
--app-version "1.0.0" ^
--copyright "Valkryst, 2020" ^
--name "Example" ^
--vendor "Valkryst" ^
--verbose ^
--icon "%~dp0..\..\res\icon\icon.ico" ^
--input "%~dp0temp" ^
--java-options "-Djdk.module.illegalAccess=permit" ^
--main-class "com.valkryst.Example.Driver" ^
--main-jar "Example-1.0-SNAPSHOT-jar-with-dependencies.jar" ^
--win-dir-chooser ^
--win-shortcut ^
--win-console

rmdir /S /Q "%~dp0temp
pause
英文:

After further investigation, it appears as though the jpackage utility doesn't support symbolic links. It wasn't packaging the Example-1.0-SNAPSHOT-jar-with-dependencies.jar into the executable, so the installed Example-1.0.0.exe was unable to load the main Driver class because it didn't exist in the installation directory.

mkdir temp
copy &quot;%~dp0..\..\target\Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot; &quot;%~dp0temp\Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot;

&quot;C:\Program Files\Java\jdk-14\bin\jpackage.exe&quot; ^
--type msi ^
--app-version &quot;1.0.0&quot; ^
--copyright &quot;Valkryst, 2020&quot; ^
--name &quot;Example&quot; ^
--vendor &quot;Valkryst&quot; ^
--verbose ^
--icon &quot;%~dp0..\..\res\icon\icon.ico&quot; ^
--input &quot;%~dp0temp&quot; ^
--java-options &quot;-Djdk.module.illegalAccess=permit&quot; ^
--main-class &quot;com.valkryst.Example.Driver&quot; ^
--main-jar &quot;Example-1.0-SNAPSHOT-jar-with-dependencies.jar&quot; ^
--win-dir-chooser ^
--win-shortcut ^
--win-console

rmdir /S /Q &quot;%~dp0temp
pause

huangapple
  • 本文由 发表于 2020年4月10日 22:49:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/61142801.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定