【问题标题】:Unable to run executable jar containing dependencies无法运行包含依赖项的可执行 jar
【发布时间】:2011-05-06 15:53:18
【问题描述】:

如果我仍然不知道如何运行由 maven 生成的可执行 jar,我会为此感到羞耻。

myapp-uberjar.jar 包含以下内容:

com/myapp/...(我所有的项目包和类都在这里) 元信息/清单.MF 依赖1.jar 依赖项2.jar ...

清单似乎也不错(为简洁起见,我在这里删除了一些依赖项):

清单版本:1.0 存档器版本:丛存档器 创建者:Apache Maven 建造者:rabdi 构建-Jdk:1.6.0_18 主类:com.myapp.core.main.Boot 类路径:spring-context-3.0.5.RELEASE.jar spring-context-support-3.0.5.RELEASE.jar spring-test-3.0.5.RELEASE.jar axis-1.4.jar axis-jaxrpc-1.4。罐轴 -saaj-1.4.jar 轴-wsdl4j-1.5.1.jar commons-discovery-0.2.jar xml-api s-1.0.b2.jar log4j-1.2.15.jar commons-pool-1.5.4.jar hamcrest-core-1.1.jar junit-de p-4.8.2.jar

现在当我运行我的 jar 时,出现以下错误:

D:\myapp\target>java -jar myapp-uberjar.jar 线程“主”java.lang.NoClassDefFoundError 中的异常:org/apache/log4j/Logger 在 com.myapp.core.main.Boot.(Boot.java:14) 引起:java.lang.ClassNotFoundException:org.apache.log4j.Logger 在 java.net.URLClassLoader$1.run(未知来源) 在 java.security.AccessController.doPrivileged(本机方法) 在 java.net.URLClassLoader.findClass(未知来源) 在 java.lang.ClassLoader.loadClass(未知来源) 在 sun.misc.Launcher$AppClassLoader.loadClass(未知来源) 在 java.lang.ClassLoader.loadClass(未知来源) ... 1 更多 找不到主类:com.myapp.core.main.Boot。程序将会退出。

为什么它不起作用?如何让它工作。

谢谢!

【问题讨论】:

标签: java build maven jar classpath


【解决方案1】:

如果你的distribute my program as single zip with my jar and libraries,那么你必须建立一个类路径。 如果您希望依赖项将 a 库放在 jar 之外(强烈推荐),您必须使用程序集插件(或其他插件)。 这是一个完整的解释如何做到这一点: pom 构建元素:

<build>
    <!-- final name set the jar name, if left it 
    will give defualt "${artifactId}-${version}" -->
    <finalName>jar final name</finalName>
    <sourceDirectory>src</sourceDirectory>

        <!-- compiler plug in -->
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
        <!-- assembly plugin -->
        <!-- the assembly plugin is used to define your 
        final deploy output (jar, zip, dir, war, etc..)-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <id>assembly:package</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <!-- The filename of the assembled distribution 
                        file defualt ${project.build.finalName}-->
                        <finalName>${project.build.finalName}</finalName>
                        <appendAssemblyId>false</appendAssemblyId>
                        <!--    A list of descriptor files path to generate from-->
                        <descriptors>
                            <descriptor>assembly/assembly.xml</descriptor>
                        </descriptors>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- jar plug in -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                        <!-- to create a class path to your 
                        dependecies you have to fill true in this field-->
                        <addClasspath>true</addClasspath>
                        <!-- if you put your dependencySet/outputDirectory 
                        in the assembly file is in a specific folder (lib for example), 
                        you need to add classpathPrefix-->
                        <classpathPrefix>lib/</classpathPrefix>

                        <!-- if you defined your dependencySet/outputFileNameMapping 
                        in the assembly, instead of using the classpathPrefix, 
                        you should use customClasspathLayout, 
                        add the classpathPrefix at the begining of the 
                        customClasspathLayout, and then add the pattern of the outputFileNameMapping, 
                        NOTICE YOU NEED TO ADD '$' BEFOR OF EACH '$'.
                        supported only from version 2.3>-->
                        <!--<classpathLayoutType>custom</classpathLayoutType>
                        <customClasspathLayout>
                            lib/$${artifact.groupId}.$${artifact.artifactId}.$${artifact.extension}
                        </customClasspathLayout>-->

                    </manifest>

                    <manifestEntries>
                        <Class-Path>conf/</Class-Path>
                    </manifestEntries>
                </archive>

            </configuration>
        </plugin>

    </plugins>
</build>

汇编文件:

<?xml version="1.0" encoding="UTF-8"?>
<assembly>
    <!--the id will be add to the end of the distribution file -->
    <id>package</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>


    <fileSets>
        <fileSet>
            <directory>target</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>*.jar</include>                
            </includes>
        </fileSet>
        <fileSet>
            <directory>icons</directory>
            <outputDirectory>icons</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>conf</directory>
            <outputDirectory>conf</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
        </fileSet>
    </fileSets>

    <files>
        <!-- you need to create the bat file yourself -->
        <file>
            <source>batFileName.bat</source>
            <filtered>true</filtered>
        </file>
    </files>

        <dependencySets>
            <dependencySet>
                <!--define the outputDirectory of the dependencies, 
                    NOTICE: if it's diffrent from '/'  make sure to 
                    change the classPath configuration for 
                    the maven-jar-plugin in the pom-->
                <outputDirectory>lib</outputDirectory>
                <!-- maping the dependencies jar names.
                    NOTICE : if you used this definition, you need to use 
                    customClasspathLayout classPath configuration 
                    for the maven-jar-plugin in the pomg-->
                <outputFileNameMapping>
                    ${artifact.groupId}.${artifact.artifactId}.${artifact.extension}
                </outputFileNameMapping>
                <unpack>false</unpack>
            </dependencySet>
        </dependencySets>

</assembly>

【讨论】:

    【解决方案2】:

    第一种可能性:Java 期望类路径上的所有这些 jar 与您的可执行 jar 位于同一目录中。是吗?

    【讨论】:

    • 您可以使用 maven-assembly-plugin 将所有依赖 jar 复制到您的目标目录
    • Jars 在我的可执行 jar (myapp-uberjar.jar) 中
    • @Hurda 是的,我会这样做,但我的问题是关于如何将我的应用程序作为单个 jar 分发。我的意思是 myapp-uberjar.jar 包含它的所有依赖项。
    • @redsonic - 为什么会这样?我确实将我的程序与我的 jar 和库一起作为单个 zip 分发...没有多少程序作为单个 .exe 分发-您总是可以将所有依赖项解压缩它们的 jar 并将所有类文件放入单个 jar...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    • 2015-09-14
    • 2012-04-12
    • 2017-02-22
    • 2021-05-25
    • 2014-09-02
    相关资源
    最近更新 更多