首页 文章

使用java运行javac编译的groovy代码?

提问于
浏览
1

我有一个简单的groovy文件如下:

class test2 {
    public static void main(String[] args) {
        println("In groovy!!");
    }
}

我的gradle任务是将它编译成test2类文件

如何从提示符运行此文件?

java test2 (从test2.class文件的位置)导致a:错误:无法找到或加载主类test2.class

我假设我需要在类路径中添加asm和groovy . 但是: java -cp "groovy-all-2.3.6.jar;asm-all-3.3.1.jar" test2 也不起作用(文件位于正确的位置) .

2 回答

  • 11

    我知道OP可能会有点迟,但是:

    鉴于您的groovy main存在,错误消息:

    错误:无法找到或加载主类YOUR_MAINCLASS_HERE

    来自 java 命令 while executing a groovy main (生成类的已编译的groovy文件)基本上意味着你的 groovy jarnot in classpath .

    更长的答案:

    让我们看看为什么这是一个简单的hello world示例 . 我有一个名为main.groovy的文件,其中包含以下内容:

    class Main {
        static void main(String[] args){
                println('hello world')
        }
    

    }

    把它放在你的文件系统中 . 在同一目录中打开命令提示符,并确保通过PATH可以访问groovy和java .

    在命令提示符下,使用groovyc编译该文件,因此只需键入:

    groovyc main.groovy
    

    这将生成一个名为 M ain.class的文件(由于类名,大写字母M) .

    好的,现在我们有适当的测试设置 . 如果您现在尝试使用java命令运行该文件:

    java Main
    

    你会收到错误信息:

    错误:无法找到或加载主类Main

    这有点出乎意料,因为我们可以认为我们可以在Main.class中调用main而不链接groovy库,所以我们期望像ClassNotFoundException这样的异常 .

    相反,在类路径中再次尝试使用groovy . 我将groovy安装的目录称为GROOVY_HOME . 要最终运行hello world Main类,我们可以输入:

    java -cp“ . :/ $ GROOVY_HOME / lib / *”Main

    它在类似unix的系统上产生预期的输出(在windows上你需要用分号替换冒号,变量访问就像%GROOVY_HOME%) .

    原因很简单:Groovy为groovy主方法生成的不是java规范所要求的相同签名 . 因此,你只能在CLASSPATH上使用groovy调用一个groovy main - 这是完全合理的!

    你可以自己检查一下 . 立即尝试命令:

    javap Main.class
    

    这将使您快速分析“Main.class”类的字节码和当前接口 . 一直以来你会看到类似于这个输出的东西:

    Compiled from "main.groovy"
    public class Main implements groovy.lang.GroovyObject {
      public static transient boolean __$stMC;
      public Main();
      public static void main(java.lang.String...);
      protected groovy.lang.MetaClass $getStaticMetaClass();
      public groovy.lang.MetaClass getMetaClass();
      public void setMetaClass(groovy.lang.MetaClass);
      public java.lang.Object invokeMethod(java.lang.String, java.lang.Object);
      public java.lang.Object getProperty(java.lang.String);
      public void setProperty(java.lang.String, java.lang.Object);
    }
    

    有趣的是第5行:

    public static void main(java.lang.String ...);

    这似乎与普通的java main非常相似,但有一点不同:groovyc使用了java.lang.String省略号(如三点所示)而不是java.lang.String [] .

    所以这可能是原因 . 我不太确定,因为如果它能找到类而不是方法签名,通常java会给你一个合适的错误输出 . 例如,尝试:

    java java.lang.Integer
    

    这显然不是主要方法 . Java正确地看到了:

    Error: Main method not found in class java.lang.Integer, please define the main method as:
    public static void main(String[] args)
    or a JavaFX application class must extend javafx.application.Application
    

    我也不确定,在类加载期间groovy做了什么来理解这种主要签名(或者让我们说这种字节码),但如果你将它与普通的java hello world javap输出进行比较,你会得到

    public class JMain { public JMain(); public static void main(java.lang.String[]); }

    它有一个不同的和普通的java主签名 .

    也许来自关键的groovy团队的人可以澄清 . 我希望这会给你一个提示 .

  • 0

    test2.class需要在你的CLASSPATH上 . 例如,如果它位于/Users/you/classes/test2.class,那么/ Users / you / classes /需要在您的CLASSPATH上 .

    由于您使用Gradle构建,因此您也可以让Gradle使用JavaExec为您排序所有这些内容 . 有关详细信息,请参阅http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html . build.gradle中的一个简单示例可能是这样的:

    task myTask(type: JavaExec, dependsOn: 'classes') {
        main = 'test2'
        classpath = sourceSets.main.runtimeClasspath
    }
    

    我希望有所帮助 .

相关问题