Java -- 为常用包创建 Jar 文件

Posted

技术标签:

【中文标题】Java -- 为常用包创建 Jar 文件【英文标题】:Java -- Creating a Jar file for common packages 【发布时间】:2016-06-07 01:28:43 【问题描述】:

我有一个问题希望有人可以帮助我。

我有两个 java 项目,我们称之为 CORE,其中包含一堆具有通用功能的类,并为我们的数据库提供休眠接口/dao 等。

其他项目需要 CORE 才能与我们的数据库交互并利用通用核心功能。

现在我已经使用 Gradle 创建了一个 Jar 文件,通过我的 IDE 将 jar 文件导入到其他项目中,一切都可以正确编译。

但是当我尝试运行其他项目时,我得到了

Java.lang.NoClassDefFoundError: 无法初始化类

现在我明白了,在创建 Jar 文件时,您需要提供一个清单文件来详细说明入口点......但是核心项目没有任何可运行的 main 方法......所以我该如何创建我的让所有其他项目都可以使用 CORE 的 Jar?

谢谢


更新

好的,所以我想我需要更多帮助(感谢迄今为止提供的所有信息)

是的,所以我在我的 gradle 文件中将 jar 作为编译和运行时依赖项

dependencies 
compile files('lib/CORE-all-1.0.jar')
runtime files('lib/CORE-all-1.0.jar')
compile 'org.testng:testng:6.9.6'
compile 'org.hamcrest:hamcrest-all:1.3'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.6.1'
compile 'com.fasterxml.jackson.core:jackson-core:2.6.1'
compile 'com.fasterxml.jackson.core:jackson-databind:2.6.1'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.6.1'
compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
compile 'org.apache.httpcomponents:httpclient:4.5'
compile 'joda-time:joda-time:2.8.2'
compile 'org.slf4j:jcl-over-slf4j:1.7.12'
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'net.sf.ehcache:ehcache:2.10.1'

如果我打印类路径,我可以看到 Jar :(

:打印类路径 /Users/xxxxx/IdeaProjects/testProject/lib/CORE-all-1.0.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.testng/testng/6.9.6/e6788337be58ddc30c01d0ade783fb06cc825c7c/testng-6.9.6.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-all/1.3/63a21ebc981131004ad02e0434e799fd7f3a8d5a/hamcrest-all-1.3.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.6.1/f9661ddd2456d523b9428651c61e34b4ebf79f4e/jackson-annotations-2.6.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.6.1/892d15011456ea3563319b27bdd612dbc89bb776/jackson-core-2.6.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.6.1/45c37a03be19f3e0db825fd7814d0bbec40b9e0/jackson-databind-2.6.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.6.1/a6fbc5b4c5622cda94d86ccfe93208b954765ccd/jackson-dataformat-xml-2.6.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.codehaus.jackson/jackson-mapper-asl/1.9.13/1ee2f2bed0e5dd29d1cb155a166e6f8d50bbddb7/jackson-mapper-asl-1.9.13.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.5/a1e6cbb3cc2c5f210dd1310ff9fcb2c09c0d1438/httpclient-4.5.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/joda-time/joda-time/2.8.2/d27c24204c5e507b16fec01006b3d0f1ec42aed4/joda-time-2.8.2.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.slf4j/jcl-over-slf4j/1.7.12/adef7a9e1263298255fdb5cb107ff171d07c82f3/jcl-over-slf4j-1.7.12.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.1.3/d90276fff414f06cb375f2057f6778cd63c6082f/logback-classic-1.1.3.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/net.sf.ehcache/ehcache/2.10.1/a507a1302b631d0718fe29ae95d4e52e646ecc5a/ehcache-2.10.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.google.inject/guice/4.0/199b7acaa05b570bbccf31be998f013963e5e752/guice-4.0-no_aop.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.beanshell/bsh/2.0b4/a05f0a0feefa8d8467ac80e16e7de071489f0d9c/bsh-2.0b4.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.apache.ant/ant/1.7.0/9746af1a485e50cf18dcb232489032a847067066/ant-1.7.0.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.beust/jcommander/1.48/bfcb96281ea3b59d626704f74bc6d625ff51cbce/jcommander-1.48.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/1.15/3b132bea69e8ee099f416044970997bde80f4ea6/snakeyaml-1.15.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/junit/junit/4.10/e4f1766ce7404a08f45d859fb9c226fc9e41a861/junit-4.10.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.6.1/6e49b856747d22cc74fd0dddf8c584de1522916c/jackson-module-jaxb-annotations-2.6。 1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.codehaus.woodstox/stax2-api/3.1.4/ac19014b1e6a7c08aad07fe114af792676b685b7/stax2-api-3.1.4.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.codehaus.jackson/jackson-core-asl/1.9.13/3c304d70f42f832e0a86d45bd437f692129299a4/jackson-core-asl-1.9.13.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.4.1/f5aa318bda4c6c8d688c9d00b90681dcd82ce636/httpcore-4.4.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.9/9ce04e34240f674bc72680f8b843b1457383161a/commons-codec-1.9.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.12/8e20852d05222dc286bf1c71d78d0531e177c317/slf4j-api-1.7.12.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.1.3/e3c02049f2dbbc764681b40094ecf0dcbc99b157/logback-core-1.1.3.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd​​51d21a231b76c915872d38/javax.inject-1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/aopalliance/aopalliance/1.0/235ba8b489512805ac13a8f9ea77a1ca5ebe3e8/aopalliance-1.0.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/16.0.1/5fa98cd1a63c99a44dd8d3b77e4762b066a5d0c5/guava-16.0.1.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.apache.ant/ant-launcher/1.7.0/e7e30789211e074aa70ef3eaea59bd5b22a7fa7a/ant-launcher-1.7.0.jar /Users/xxxxx/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.1/860340562250678d1a344907ac75754e259cdb14/hamcrest-core-1.1.jar

我仍然看到错误:(

【问题讨论】:

我不认为所有 JAR 都必须有一个入口点(你称之为主类).. 其他什么样的项目以及您如何尝试运行它? 仅供参考,它是另一个 Java 项目。并且 jar 是通过 IDE 作为依赖项添加的。 它的编译也很好,因为它可以看到所有的类。但是,当它运行时会吐出该错误 这是一个运行时类路径错误,而不是编译时错误。显然,您的编译类路径很好。出现问题的是您的运行时类路径。核心库需要包含在 jar 中并在清单的 Class-Path 变量中引用,或者它是外部的并通过调用的类路径直接引用以运行应用程序 jar(或环境变量,如果您愿意) . 【参考方案1】:

如果您的 JAR 文件是一个库,则它不会在其 MANIFEST.MF 中获得 Main-Class 条目。库支持其他程序,它们不运行。

如果您的 JAR 文件是一个程序,则它需要在其 MANIFEST.MF 中包含 Main-Class 条目,并且清单可能应该在 MANIFEST.MF 中使用 Class-Path 条目提及所需的 JAR 文件。

如果您的 JAR 文件是嵌入在其他程序中的程序(不应该,但确实发生了),其他程序将控制启动行为。没有“库提供的程序启动器”之类的东西。

有 Java 框架,它们是缺少关键功能的程序。在这种情况下,您的代码基本上是框架加载和运行的库,向 JAR 文件添加主类不会影响框架的主类行为,因为框架是启动程序。

考虑到这一点,IDE 通常会维护一个单独的运行配置,该配置并不总是遵循您可能在命令行上使用的约定。您应该检查您的 IDE 运行配置,如果可能,将它们与所需的命令行调用链对齐,或采取措施确保它们不会分开。在您的情况下,您的 IDE 很可能缺少同一 CLASS_PATH 上的两个 JAR 文件,但是如何修复这些文件的详细信息是特定于您的 IDE 和您创建的类型或项目的。

【讨论】:

"如果你的 JAR 文件是一个库,它的 MANIFEST.MF 中没有 Main-Class 条目。库支持其他程序,它们不会运行。"这正是我的想法,感谢您的确认。所以我尝试通过 gradle 构建/编译它并没有抱怨。但是,在运行需要 jar 的项目时,它仍然会引发异常......我不知道现在可以做什么?? 可悲的是我可以在类路径上看到 jar,但我仍然看到错误?如果您可以看一下,我已经粘贴了类路径和 Gradle 依赖项 如果您的 JAR 文件中有 Class-Path 条目,则环境类路径将被忽略。使用其中一种,但不能同时使用两者。【参考方案2】:

你肯定有一个类路径问题。

如果您从 IDE 运行项目,您还需要添加核心依赖项(如休眠)。

Gradle 可以使用 idea 插件更新您的类路径:https://docs.gradle.org/current/userguide/idea_plugin.html

如果您在命令行中运行项目,您需要使用类路径选项指定所有依赖项。例如:java -cp "Test.jar;lib/*" my.package.MainClass

或者您可以使用 wildfly-swarm 或 onejar 创建一个 uberjar。

【讨论】:

【参考方案3】:

您的核心 jar 只需包含在任何使用它的应用程序的类路径中。

例如

java -cp core.jar;app.jar path.to.main.class.in.app.jar

或者您可以在构建时将核心 jar 包裹在您的应用程序 jar 中,并在清单中添加一些值,如下所示:

Class-Path: core.jar
Main-Class: path.to.main.class.in.app.jar

然后构建app.jar,在根目录下包含core.jar...

jar cfm app.jar MANIFEST.MF pathToClasses core.jar

并通过...调用

java -jar app.jar

在本例中,core.jar 包含在类路径中,app.jar 已经知道它的主类,因此调用更简单。

或者用 sbt-assembly 或 onejar 之类的东西创建一个“胖罐子”。

【讨论】:

遗憾的是,我可以在类路径上看到 jar,但仍然看到错误?如果您可以看一下,我已经粘贴了类路径和 Gradle 依赖项

以上是关于Java -- 为常用包创建 Jar 文件的主要内容,如果未能解决你的问题,请参考以下文章

jar包是啥,做啥用的?

常用jar命令与

java中常用jar包

maven常用的lifecycle,clean/install/deploy,maven打包jar包,maven打包强制拉取最新依赖

java开发常用jar包

4-7《Java的调试与优化(IDEA)》——junit单元测试debug调试IDEA常用快捷键