Gradle - 找不到或加载主类

102

我正在尝试使用Gradle运行一个非常简单的项目,但在使用gradlew run命令时遇到以下错误:

找不到或无法加载主类'hello.HelloWorld'

这是我的文件结构:

SpringTest
    -src
        -hello
            -HelloWorld.java
            -Greeter.java
    -build
         -libs
         -tmp
    -gradle
         -wrapper
    -build.gradle
    -gradlew
    -gradlew.bat

我排除了 libs 和 tmp 文件夹的内容,因为我认为这些信息与此问题无关,但如果需要,我可以添加进去。

这是我的 build.gradle 文件:

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'eclipse'

mainClassName = 'hello/HelloWorld'

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    compile "joda-time:joda-time:2.2"
}

jar {
    baseName = "gs-gradle"
    version = "0.1.0"
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}
任何解决这个问题的想法吗?我已经尝试了各种针对 mainClassName 属性的方法,但似乎没有什么作用。

不应用 application 是否也隐式应用了 java 插件? - nabster
16个回答

90

我在这里看到两个问题,一个是关于 sourceSet,另一个是关于 mainClassName

  1. 要么将 Java 源文件移动到 src/main/java 中而不是只有 src。或者通过在 build.gradle 中添加以下内容来正确设置 sourceSet

sourceSets.main.java.srcDirs = ['src']
  • mainClassName 应该是完整的类名,而不是路径。

  • mainClassName = "hello.HelloWorld"
    

    1
    我在哪里更改sourceSets?是在我的build.gradle文件中吗?还是有一个需要更改的配置文件? - kibowki
    2
    当我添加了sourceSets.main.java.srcDirs = ['src']时,在jar任务中出现了错误。 - Victor M Perez
    2
    MissingPropertyException: 无法设置未知属性'mainClassName',适用于Gradlew 4.1 - fuat
    1
    @fuat,你需要安装应用程序插件。 - VFX
    1
    “Could not set unknown property 'mainClassName' for root project”错误。请显示完整的build.gradle文件。 - parsecer

    35

    修改 build.gradle 将您的主类放入清单文件中:

    jar {
        manifest {
            attributes 'Implementation-Title': 'Gradle Quickstart',
                       'Implementation-Version': version,
                       'Main-Class': 'hello.helloWorld'
        }
    }
    

    29

    我刚刚遇到了这个问题,因为在互联网上找不到解决方案,所以决定自己调试。我所做的就是将mainClassName更改为其完整路径(当然,在项目中包含正确的子目录)。

        mainClassName = 'main.java.hello.HelloWorld'
    

    我知道这篇文章已经发布了将近一年,但我认为有人会发现这些信息很有用。

    祝编码愉快。


    10

    针对试图从Netbeans运行Gradle项目的新手,为了让事情更清晰明了:
    您需要查看主类名称以及Gradle构建的外观才能理解这一点:

    主类:

    package com.stormtrident;
    
    public class StormTrident {
        public static void main(String[] cmdArgs) {
        }
    }
    

    请注意它是"com.stormtrident"包的一部分。

    Gradle构建:

    apply plugin: 'java'
    
    defaultTasks 'jar'
    
    jar {
     from {
            (configurations.runtime).collect {
                it.isDirectory() ? it : zipTree(it)
            }
        }    
        manifest {
            attributes 'Main-Class': 'com.stormtrident.StormTrident'
        }
    }
    
    
    sourceCompatibility = '1.8'
    [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
    
    if (!hasProperty('mainClass')) {
        ext.mainClass = 'com.stormtrident.StormTrident'
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        //---apache storm
        compile 'org.apache.storm:storm-core:1.0.0'  //compile 
        testCompile group: 'junit', name: 'junit', version: '4.10'
    }
    

    1
    对我来说,添加你的 jar { manifest { attributes } } 部分很有帮助。谢谢! - Paul
    Netbeans在做什么不同的事情,以至于Gradle似乎被不同地运行了?我正在尝试手动操作,以便更好地理解Gradle。Netbeans似乎非常擅长Maven,但是在Netbeans中使用Gradle似乎很脆弱。 - cody.tv.weber

    3

    我曾经遇到过同样的问题。但是在创建目录结构src/main/java并将源码(从包的顶部开始)放入后,它按照预期运行。

    我试用的教程。在执行gradle build之后,您应该能够在build目录下找到classes


    1
    另外,因为没有其他人指定:build.gradle 文件必须位于 src/ 目录旁边,而不是与 src/main/java/hello/ 中的 .java 文件一起。 - joakimk

    3
    对于NetBeans 11用户,这对我有效:
    apply plugin: 'java'
    apply plugin: 'application'
    
    // This comes out to package + '.' + mainClassName
    mainClassName = 'com.hello.JavaApplication1'
    

    这是我的树的结构:

    C:\...\NETBEANSPROJECTS\JAVAAPPLICATION1
    │   build.gradle
    ├───src
    │   ├───main
    │   │   └───java
    │   │       └───com
    │   │           └───hello
    │   │                   JavaApplication1.java
    │   │
    │   └───test
    │       └───java
    └───test
    

    2

    我通过运行 gradle build 的清理操作(或手动删除 gradle build 文件夹)来修复了这个问题。

    当您将主类移动到新的包中,旧的主类仍然被类路径引用时,就会发生这种情况。


    1
    构建/清理 + 构建/构建会生成构建,但不能解决运行时问题。 - MonoThreaded
    删除构建文件在我重命名源代码树的一部分后拯救了我的生命。谢谢! - undefined

    2
    如果你决定用Kotlin编写你的hello.World类,另一个问题可能是你需要将其引用为mainClassName = "hello.WorldKt"

    src/main/java/hello/World.kt:

    package hello
    fun main(args: Array<String>) {
        ...
    }
    // class World {} // this line is not necessary
    

    1
    在我的build.gradle中,我通过创建一个任务并指定"mainClassName"来解决了这个问题,具体如下:
    task(runSimpleXYZProgram, group: 'algorithms', description: 'Description of what your program does', dependsOn: 'classes', type: JavaExec) {
        mainClassName = 'your.entire.package.classContainingYourMainMethod'
    }
    

    0
    我通过在我的应用程序中添加以下代码来解决它。
    // 在此输入代码 这是我运行build.gradle时遇到的错误。主类名尚未配置,因此无法解析。
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    

    这已经是一个SpringBoot项目启动的入口了,问题是关于配置冲突而不是如何初始化项目。 - aya salama

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接