Maven打包JavaFX应用时Main-Class未写入MANIFEST.MF求助
问题现象
执行java -jar BadDDOS-1.0-SNAPSHOT.jar时提示:
no main manifest attribute, in BadDDOS-1.0-SNAPSHOT.jar
打包后的Jar内MANIFEST.MF缺少Main-Class属性,内容如下:
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven 3.8.5 Built-By: Jason Build-Jdk: 21.0.2
Jar结构确认包含主类文件(me/jason/badddos/Application.class),完整结构:
META-INF/ META-INF/MANIFEST.MF me/ me/jason/ me/jason/badddos/ me/jason/badddos/css/ me/jason/badddos/fxml/ me/jason/badddos/misc/ me/jason/badddos/skins/ me/jason/badddos/Application.class me/jason/badddos/css/home-style.css me/jason/badddos/DDOS.class me/jason/badddos/fxml/home-view.fxml me/jason/badddos/Home_Controller.class me/jason/badddos/misc/shrek.jpg me/jason/badddos/skins/ddosBtn_Skin.class module-info.class META-INF/maven/ META-INF/maven/me.jason/ META-INF/maven/me.jason/BadDDOS/ META-INF/maven/me.jason/BadDDOS/pom.xml META-INF/maven/me.jason/BadDDOS/pom.properties
配置情况
已在pom.xml的javafx-maven-plugin中配置<mainClass>me.jason.badddos.Application</mainClass>,完整pom.xml内容:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>me.jason</groupId> <artifactId>BadDDOS</artifactId> <version>1.0-SNAPSHOT</version> <name>BadDDOS</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <junit.version>5.10.0</junit.version> </properties> <dependencies> <dependency> <groupId>com.github.akman</groupId> <artifactId>jpackage-maven-plugin</artifactId> <version>0.1.5</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>21</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>21</version> </dependency> <dependency> <groupId>org.controlsfx</groupId> <artifactId>controlsfx</artifactId> <version>11.1.2</version> </dependency> <dependency> <groupId>org.kordamp.ikonli</groupId> <artifactId>ikonli-javafx</artifactId> <version>12.3.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>21</source> <target>21</target> </configuration> </plugin> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <executions> <execution> <id>default-cli</id> <configuration> <mainClass>me.jason.badddos.Application</mainClass> <launcher>app</launcher> <jlinkZipName>app</jlinkZipName> <jlinkImageName>app</jlinkImageName> <noManPages>true</noManPages> <stripDebug>true</stripDebug> <noHeaderFiles>true</noHeaderFiles> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
原因分析
javafx-maven-plugin的默认执行目标是javafx:run,仅用于运行应用,不会负责生成包含Main-Class的可执行Jar。当前打包操作实际是maven-jar-plugin的默认jar目标完成的,而该插件未配置主类信息,因此生成的Jar没有Main-Class属性。
解决方案
方案1:配置maven-jar-plugin添加主类信息
在pom.xml的<build><plugins>中添加maven-jar-plugin配置,指定主类:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <mainClass>me.jason.badddos.Application</mainClass> <addClasspath>true</addClasspath> </manifest> </archive> </configuration> </plugin>
注意:这种方式生成的Jar需要依赖JavaFX运行时环境,运行时需确保JavaFX库在类路径中,或使用--module-path指定JavaFX模块路径。
方案2:使用javafx-maven-plugin生成可执行Jar
修改javafx-maven-plugin的配置,添加javafx:jar执行目标,该目标会生成包含JavaFX依赖的可执行Jar:
<plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <executions> <execution> <id>default-cli</id> <configuration> <mainClass>me.jason.badddos.Application</mainClass> <launcher>app</launcher> <jlinkZipName>app</jlinkZipName> <jlinkImageName>app</jlinkImageName> <noManPages>true</noManPages> <stripDebug>true</stripDebug> <noHeaderFiles>true</noHeaderFiles> </configuration> </execution> <execution> <id>default-jar</id> <goals> <goal>jar</goal> </goals> <configuration> <mainClass>me.jason.badddos.Application</mainClass> </configuration> </execution> </executions> </plugin>
执行打包命令:mvn clean package,生成的Jar会包含Main-Class属性,且内置JavaFX依赖。
方案3:使用jlink生成模块化运行镜像(推荐)
如果项目是模块化项目(存在module-info.class),可以使用javafx-maven-plugin的jlink目标生成独立的运行镜像,无需依赖系统JavaFX环境:
<plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <executions> <execution> <id>default-cli</id> <configuration> <mainClass>me.jason.badddos.Application</mainClass> <launcher>app</launcher> <jlinkZipName>app</jlinkZipName> <jlinkImageName>app</jlinkImageName> <noManPages>true</noManPages> <stripDebug>true</stripDebug> <noHeaderFiles>true</noHeaderFiles> </configuration> <goals> <goal>jlink</goal> </goals> </execution> </executions> </plugin>
执行命令:mvn clean javafx:jlink,生成的app目录中包含可执行启动脚本,直接运行即可。
内容的提问来源于stack exchange,提问作者crjase

