简体   繁体   English

移至Maven后,我的已编译jar文件无法运行

[英]After moving to maven, my compiled jar file doesn't run

It actually took me a long while to notice. 实际上,我花了很长时间才注意到。 When I run the project in netbeans, it works just as expected. 当我在netbeans中运行该项目时,它按预期运行。 But when I do the Build I get PROJECTNAME-1.0-SNAPSHOT.jar file that doesn't do anything. 但是,当我执行Build我得到了没有执行任何操作的PROJECTNAME-1.0-SNAPSHOT.jar文件。 When unpacked, it looks like this: 打开包装后,它看起来像这样:

图片描述

This is suspicious, before Maven, my compiled file looked like this: 这很可疑,在Maven之前,我的编译文件如下所示:

图片描述

Shouldn't the Main class be in the jar file root? Main类不应该在jar文件的根目录中吗? How does JVM know which main class to run? JVM如何知道要运行哪个主类?

There's something disturbing about the MANIFEST.MF too: MANIFEST.MF也有一些令人不安的地方:

Old manifest 旧清单

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.1
Created-By: 1.7.0_45-b18 (Oracle Corporation)
Class-Path: lib/alloy.jar lib/jna-platform.jar lib/jna.jar
X-COMMENT: Main-Class will be added automatically by build
Main-Class: Main

New manifest 新清单

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Jakub
Build-Jdk: 1.8.0_31

Seems like Main-Class entry is missing... 好像缺少Main-Class条目...

Use maven-jar-plugin for make your jar executable. 使用maven-jar-plugin使您的jar可执行文件。 For me actual code below: 对我来说,下面的实际代码:

 <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.5</version>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>my.main.class</mainClass>
            </manifest>
          </archive>
          <outputDirectory>${project.build.directory}/result</outputDirectory>
        </configuration>
      </plugin>

Alse usefull exec-maven-plugin : 还有用exec-maven-plugin

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.3.2</version>
    <configuration>
      <mainClass>my.main.class</mainClass>
      <!--
      <commandlineArgs>-d 5409  -c 467 -t 2  -dlg true</commandlineArgs>
      -->
    </configuration>
  </plugin>

Sadly many IDE's provide a simple mechanism for packaging all of your library jars into your main build jar. 遗憾的是,许多IDE提供了一种简单的机制,用于将所有库jar打包到主构建jar中。 This is both frowned-upon and potentially hazardous to your deployable - you should really deploy all of the used libraries separately and use your class-path to join them all up. 这既皱眉,又可能对您的可部署程序造成危险-您应该真正单独部署所有使用的库,并使用类路径将它们全部加入。

As Maven attempts to make doing it right the easiest way it is designed to by default build your jar to contain just your code and no more. 当Maven尝试正确地做正确的事时,默认情况下,它被设计为构建jar,使其仅包含代码,而不再包含其他代码。 If you can stick with this solution then it may be worth your while doing so. 如果您可以坚持使用此解决方案,那么这样做可能是值得的。

However, sometimes it is necessary to make this happen, perhaps to duplicate existing build results while switching to Maven or maybe deployment is enough of a nightmare without having to deploy dozens of libraraies too. 但是,有时有必要做到这一点,也许在切换到Maven时复制现有的构建结果,或者部署就足够进行噩梦而不必部署数十个库。 To achieve this you can build what the Maven community call an Uber-Jar using the Maven Shade plugin. 为此,您可以使用Maven Shade插件构建Maven社区所谓的Uber-Jar。

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>1.6</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
        <configuration>
          <minimizeJar>true</minimizeJar>
          <filters>
            <filter>
              <!-- Make sure jaxb is included. -->
              <artifact>com.sun.xml.bind:jaxb-impl</artifact>
              <includes>
                <include>*.*</include>
              </includes>
            </filter> 
            <filter>
              <!-- Make sure jtds is included. -->
              <artifact>net.sourceforge.jtds:jtds</artifact>
              <includes>
                <include>**</include>
              </includes>
            </filter> 
            <filter>
              <artifact>*:*</artifact>
              <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
                <exclude>META-INF/*.sf</exclude>
                <exclude>META-INF/*.dsa</exclude>
                <exclude>META-INF/*.rsa</exclude>
              </excludes>
            </filter>
          </filters>
        </configuration>
      </execution>
    </executions>
  </plugin>

Note that building uber-jars is generally not the best approach - there are many discussions about this online. 请注意,构建uber-jars通常不是最好的方法-在线对此有很多讨论。 Also there are many relational problems with the maven-shade-plugin itself as it interferes with Maven's mechanism for determining dependencies. 此外,由于maven-shade-plugin本身会干扰Maven的确定依赖关系的机制,因此存在许多关系问题。

That said - if you must do it then the shade plugin is your guy. 就是说-如果您必须这样做,那么阴影插件就是您的理想选择。

NB: Just because this excludes licences does not mean this is a good idea - this is there to avoid duplicate file name issues in the uber jar. 注意:仅仅因为这不包括许可证并不意味着这是个好主意-这样做是为了避免uber jar中出现重复的文件名问题。

See this interesting blog by MKYong about the pros and cons of using assembly/shade/one-jar . 请参阅MKYong撰写的这个有趣的博客,了解使用assembly/shade/one-jar优缺点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM