Java Maven不包括LWJGL安装的清单属性

Java Maven不包括LWJGL安装的清单属性,java,eclipse,maven,lwjgl,pom.xml,Java,Eclipse,Maven,Lwjgl,Pom.xml,我正在尝试使用Maven设置LWJGL项目。我使用的示例“getting started”源代码来自 这包括访问LWJGL清单属性的几行代码,例如简单的版本检查: System.out.println("Hello LWJGL " + Version.getVersion() + "!"); 这在Eclipse环境中运行时没有任何问题(当然是在使用Maven构建项目之后),但是当运行clean install然后通过cmd运行**-jar with dependencies.jar时,会抛出以

我正在尝试使用Maven设置LWJGL项目。我使用的示例“getting started”源代码来自

这包括访问LWJGL清单属性的几行代码,例如简单的版本检查:

System.out.println("Hello LWJGL " + Version.getVersion() + "!");
这在Eclipse环境中运行时没有任何问题(当然是在使用Maven构建项目之后),但是当运行
clean install
然后通过cmd运行
**-jar with dependencies.jar
时,会抛出以下异常:

java.lang.NullPointerException
        at org.lwjgl.system.APIUtil.apiGetManifestValue(APIUtil.java:97)
        at org.lwjgl.Version.getVersion(Version.java:33)
        at HelloWorld.run(HelloWorld.java:43)
        at HelloWorld.main(HelloWorld.java:130)
这是因为
APIUtil
创建的
Manifest
对象不包含任何属性-,而只包含在Maven的构建版本中

这是为什么?是我的pom.xml问题还是LWJGL 3.0.0还没有准备好

这是我的
pom.xml

<properties>
    <mainClass>HelloWorld</mainClass>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <finalName>${project.artifactId}-${project.version}.jar</finalName>
</properties>

<dependencies>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-windows</classifier>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-linux</classifier>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-osx</classifier>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>${mainClass}</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

你好世界
UTF-8
${project.artifactId}-${project.version}.jar
org.lwjgl
lwjgl
3.0.0
org.lwjgl
lwjgl平台
3.0.0
本地人窗口
org.lwjgl
lwjgl平台
3.0.0
本地linux
org.lwjgl
lwjgl平台
3.0.0
本地人osx
org.apache.maven.plugins
maven编译器插件
3.5.1
1.8
1.8
org.apache.maven.plugins
maven汇编插件
包裹
单一的
带有依赖项的jar
${mainClass}

发生此错误是因为LWJGL 3.0.0,但在制作uber jar时,未设置此属性

这并不是您如何制作uber jar的问题:由
maven assembly plugin
创建的清单如下所示:

清单版本:1.0
Archiver版本:丛式Archiver
建造人:我
创建人:ApacheMaven 3.3.9
构建Jdk:1.8.0_102
主类:HelloWorld
您可以在带有依赖项的
jar的
META-INF/MANIFEST.MF
中看到它。此文件没有
“实现版本”
属性。这是正常的:当创建这个可执行JAR时,所有依赖项的所有清单都被(正确地)忽略,只生成一个包含
“Main Class”
,这样JAR才是可执行的

uber jar不能包含每个依赖项清单中的内容。例如,
“实现版本”
是多个库的清单中存在的一个属性,那么它应该保留哪一个?(在uber jar中,最后只能有一个清单)。所以问题出现了,因为我们正在制作一个可执行JAR,它只能有一个清单,所以它不能聚合每个依赖项清单中的所有属性

有两种可能的解决方案:

  • 别理它。毕竟,这并不是一个真正的错误
  • 不要通过将所有依赖项嵌入一个jar中来创建一个可执行jar,而是在
    lib
    文件夹中创建一个包含每个依赖项的ZIP程序集:这样,每个清单都将被保留。这是通过告诉
    maven jar插件
    在添加类路径的同时为主类添加清单条目并创建自定义程序集描述符来实现的

    <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>${mainClass}</mainClass>
                    <addClasspath>true</addClasspath>
                </manifest>
            </archive>
        </configuration>
    </plugin>
    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.6</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptors>
                <descriptor>/path/to/assembly.xml</descriptor>
            </descriptors>
        </configuration>
    </plugin>
    
    使用这种配置,运行
    mvn clean install
    将创建一个ZIP文件
    artifactId-version-dist.ZIP
    。解包并运行(用JAR的
    最终名称替换

    java-jarlib\.jar
    
    将打印没有任何问题的版本


  • 回答得很好,很清楚。我不太喜欢第二个选项,因为它使用户运行程序更加困难。是否有在主jar中包含jar的选项?这样行吗?此外,忽略它也不是一个选项,因为LWJGL在初始化某些类时在静态块中调用这些方法(例如,Libary调用checkHash(),它将实际库哈希与清单中存储的值进行比较)。@Frithjof No将库jar包括在主jar中是不起作用的。JAR将被视为资源,它们包含的类将不在类路径中(请参阅)。在第二个选项中,它与第一个选项一样简单:您需要解压缩一个ZIP文件并运行与前面相同的命令。如果问题是JAR太多(因此无法确定运行哪一个),您可以在ZIP的根目录下添加一个shell脚本(
    start.bat
    /
    start.sh
    ),然后执行此shell脚本。(与Maven发行版本身捆绑的内容非常相似。)另一种解决方案是让主工件不在
    lib
    文件夹内,而是在它之外的ZIP根目录下。然后您可以运行
    java-jarfinalname.jar
    ,不必担心
    lib
    中的内容。需要的改变:1<程序集描述符2中的代码>false
    (而不是
    true
    )。添加描述符
    ${project.build.directory}/${project.finalName}.jar/
    以复制主jar和3。在Jar插件配置中添加
    lib
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
      <id>dist</id>
      <formats>
        <format>zip</format>
      </formats>
      <dependencySets>
        <dependencySet>
          <outputDirectory>lib</outputDirectory>
          <useProjectArtifact>true</useProjectArtifact>
        </dependencySet>
      </dependencySets>
    </assembly>