首页 > 解决方案 > 在 cmd 中运行基于 gradle 的 Java 应用程序时出现 ClassNotFoundException

问题描述

我有一个基于简单 Gradle 的 Java 项目,在文件夹gradle build下创建了 jar之后。build/libs当我尝试使用java -jar discord-notification-bot-1.0-SNAPSHOT.jar以下路径在 cmd 中运行时

F:\github projects\discord-notification-bot\build\libs>

我低于错误

Exception in thread "main" java.lang.NoClassDefFoundError: org/javacord/api/DiscordApiBuilder
        at Application.main(Application.java:8)
Caused by: java.lang.ClassNotFoundException: org.javacord.api.DiscordApiBuilder
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

构建.gradle

plugins {
    id 'java'
}

group 'org.test'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.javacord:javacord:3.0.6'
}

jar {
    manifest {
        attributes(
                'Main-Class': 'Application'
        )
    }
}

在 src/Application.java 下

import org.javacord.api.DiscordApi;
import org.javacord.api.DiscordApiBuilder;

public class Application {
    public static void main(String[] args) {
        String key = System.getenv().get("key");
        DiscordApi api = new DiscordApiBuilder().setToken(key).login().join();
        
        System.out.println("you can invite the bot by using following url "+api.createBotInvite());
    }
}

当我通过 cmd 运行时,似乎javacord库没有得到反映。

注意:在 MANIFEST.MF 我有正确的主应用程序。但是在通过 cmd 运行时,依赖性并没有得到反映。

那么,我该怎么做呢?

标签: javagradle

解决方案


默认情况下,gradlejava插件不会将类路径信息添加到生成的 JAR 中。您可以像添加主类一样添加此信息,但最好使用gradle applicationplugin

使用该application插件,您将获得一个存档文件作为输出,它捆绑了所有依赖项和一些 bat/sh 文件以及执行。带有应用程序插件的简单 gradle 文件可能如下所示:

plugins {
  // Apply the application plugin to add support for building a CLI application in Java.
  id 'application'
}

repositories {
  // Use JCenter for resolving dependencies.
  jcenter()
}

dependencies {
  // This dependency is used by the application.
  implementation 'com.google.guava:guava:29.0-jre'
}

application {
  // Define the main class for the application.
  mainClass = 'gradle.application.App'
}

正如评论中提到的,另一个解决方案可能是使用com.github.johnrengelman.shadowplugin创建一个 shadow/fat/uber-jar 。这将产生这个基本的 gradle 文件:

plugins {
  id 'java'
  // Apply the shadow plugin to add support for building a shadow-jar
  id "com.github.johnrengelman.shadow" version "6.1.0"
}

repositories {
  // Use JCenter for resolving dependencies.
  jcenter()
}

dependencies {
  // This dependency is used by the application.
  implementation 'com.google.guava:guava:29.0-jre'
}

jar {
  manifest {
    attributes(
      'Main-Class': 'Application'
    )
  }
}

使用 shadow-plugin 您可以获得一个额外的任务shadowJar,该任务将创建一个包含所有依赖项的 JAR。虽然这听起来很方便,但它也有一些缺点,例如使用 shadow-jar 作为依赖项本身时,可能需要额外的配置。但是,在您的情况下,这可能是最佳选择。


推荐阅读