【问题标题】:How to run java project from command line (works fine in eclipse, gradle)如何从命令行运行 java 项目(在 eclipse、gradle 中运行良好)
【发布时间】:2020-07-19 11:51:38
【问题描述】:

我有一个简单的 java 程序。我正在使用 gradle 在 Eclipse 中进行开发,并且正在使用 log4j2 进行日志记录。这一切都很好。

当我从命令行运行时,我做了一个 gradlew 构建,它可以工作,但是当我运行 jar 时出现错误:

java -jar build\libs\testproj.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager
        at com.xxxxxx.practice.App.<clinit>(App.java:17)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.LogManager
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 1 more

我可以在我的 userprofile.gradle 文件夹中看到一堆 log4j 文件,我可以运行一个 gradle dist 任务,然后获取并解压缩生成的 zip 文件,然后指向其中的内容,但如果有一些方法避免这个?当然,我可以在清单中添加一些东西,或者我可以随意从命令行运行而没有开销?

要清楚,只是日志记录有这个问题。除了它运行之外,还可以从命令行进行测试等工作,并且在 eclipse 中可以正常进行日志记录。

【问题讨论】:

  • 在运行配置中有一个按钮显示命令行来获取Eclipse使用的命令行。
  • @howlger 谢谢。我只是尝试只使用类路径部分,并像以前一样指定我的 jar,但我遇到了同样的问题。另外,即使这样有效,您通常会这样做吗?我有点期待像 gradle 任务这样的东西会为我做这种事情。否则,假设可行,我可能会更好地沿着“构建一个 dist”路线走下去。
  • 您可以添加您的build.gradle 文件吗?

标签: java eclipse gradle


【解决方案1】:

在您的 Eclipse 项目中的某个地方,您会找到一个名为 log4j.jarorg.apache.logging-log4j.jarlog4j-api.jar 或类似内容的库(以 .jar 结尾)。

此 jar 包含在命令行上运行时缺少的类。试试看:jar tvf log4j.jar 打印 jar 的内容,你会发现它包含,例如,org/apache/logging/log4j/LogManager.class

在编译期间在运行java应用期间,这个类需要在类路径中。 Eclipse 负责它的编译部分。

如果您以java com.foo.ClassName 运行java,则类路径由-cp 参数定义:java -cp testproj.jar:log4j.jar com.foo.yourapp.TestApp 可以工作(在Windows 上使用分号代替)。如果不指定,系统环境变量CLASSPATH会被使用,但你不希望这样(毕竟你可以在一台机器上运行多个java应用,所以全局设置意义不大)。

但是,如果您使用java -jar myjar.jar 运行 java,则类路径仅取自 jar 文件本身; jar 文件内部是一个名为META-INF/MANIFEST.MF 的文件,它包含(以文本形式)键/值对。相关的是Class-Path: foo.jar bar.jar 条目:jar 文件的空格分隔列表,相对于您的 jar 所在的目录。

在使用-jar 选项时不能使用-cp 选项; -cp 选项被忽略

那么,接下来的步骤:

  1. 我不知道 gradle 是否正确创建了 Class-Path 条目。最好的选择是使用jarzip 工具来解压你的jar 来检查MANIFEST.MF 文件,看看里面有什么。例如,如果该文件中有Class-Path: lib/log4j.jar,则确保如果testapp.jar 位于/Users/Dev123456/project/testapp.jar,那么该log4j jar 位于/Users/Dev123456/project/lib/log4j.jar。如果没有类路径条目,则错误在于您的 gradle 配置;在这种情况下,您必须发布您的 build.gradle 文件。

  2. 有“striper 插件”将所有不同的 jar 混合在一个巨大的 jar 中。这通常是一个坏主意(它只会使 jar 本身变得庞大,并使构建花费更长的时间。如果您将 java 代码部署到服务器,您可以自己管理 Class-Path 条目,如果您正在制作桌面应用程序,您需要一个安装程序,它......也可以管理类路径的东西。真的没有理由使用条带器)。我建议不要使用这些。

  3. 只需使用java -cp yourapp.jar:dep1.jar:dep2.jar com.foo.fullyqualified.ClassName 运行即可。

【讨论】:

    【解决方案2】:

    尝试通过在类路径中指定 Log4j jar 来运行您的 jar,然后从 testproj.jar 中提及您的 MainClass:

    java -cp build\libs\testproj.jar:build\libs\log4j.jar com.package.MainClass
    

    【讨论】:

      猜你喜欢
      • 2011-06-18
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      相关资源
      最近更新 更多