简体   繁体   English

使用Java运行Javac编译的Groovy代码?

[英]Run javac compiled groovy code using java?

I have a simple groovy file as follows: 我有一个简单的常规文件,如下所示:

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

My gradle task is compiling this into a test2 class file 我的gradle任务是将其编译到test2类文件中

How do I run this file from prompt ? 如何从提示符运行此文件?

java test2 (from the location of the test2.class file) causes a : Error: Could not find or load main class test2.class java test2 (从test2.class文件的位置)导致以下错误:无法找到或加载主类test2.class

I assuming I need to add asm and groovy to the class path. 我假设我需要在类路径中添加asm和groovy。 However: java -cp "groovy-all-2.3.6.jar;asm-all-3.3.1.jar" test2 also doesn't work (files are in correct locations). 但是: java -cp“ groovy-all-2.3.6.jar; asm-all-3.3.1.jar” test2也不起作用(文件位于正确的位置)。

I know this may be a bit late for the OP but nevertheless: 我知道对于OP来说可能有点晚了,但是:

Given that your groovy main exists, the error message: 考虑到您的常规主目录存在,错误消息:

Error: Could not find or load main class YOUR_MAINCLASS_HERE 错误:找不到或加载主类YOUR_MAINCLASS_HERE

from the java command while executing a groovy main (of a compiled groovy file which produced classes) means basically that your groovy jar is not in the classpath . Java命令执行groovy main (生成类的已编译groovy文件的代码)时,基本上意味着您的groovy jar 不在 classpath中

Longer Answer: 更长的答案:

Lets see why that is for a simple hello world example. 让我们看看为什么这是一个简单的hello world示例。 I have a file called main.groovy with the following content: 我有一个名为main.groovy的文件,其内容如下:

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

} }

Put this somewhere in your filesystem. 将其放在文件系统中的某个位置。 Open a command prompt in the same directory and ensure that groovy and java is accessable though the PATH. 在同一目录中打开命令提示符,并确保可通过PATH访问groovy和Java。

In the command prompt, compile the file with groovyc , so just type in: 在命令提示符下,使用groovyc编译文件,因此只需输入:

groovyc main.groovy

This will produce a file called M ain.class (with uppercase M because of the class name). 这将产生一个名为M ain.class的文件(由于类名而大写M)。

Ok now we have the appropriate test setup. 好的,现在我们有了适当的测试设置。 If you now try to run the file just with java command: 如果现在尝试仅使用java命令运行文件:

java Main 

you will get the error message: 您将收到错误消息:

Error: Could not find or load main class Main 错误:找不到或加载主类Main

This is a bit unexpected, because one can think that we just can invoke the main in our Main.class without linking the groovy library, so we would expect an exception like ClassNotFoundException. 这有点出乎意料,因为人们可能认为我们可以在不链接groovy库的情况下调用Main.class中的main,因此我们会期望像ClassNotFoundException这样的异常。

In contrast, try again with groovy in your classpath. 相反,请在类路径中尝试使用groovy。 I will refer to the directory of your groovy installation as GROOVY_HOME. 我将把您的groovy安装目录称为GROOVY_HOME。 To run the hello world Main class finally, we can type in: 要最终运行hello world Main类,我们可以输入:

java -cp ".:/$GROOVY_HOME/lib/*" Main java -cp“。:/ $ GROOVY_HOME / lib / *”主要

which produces the expected output on unix-like systems (on windows you need to replace the colon with a semicolon and the variable access would be like %GROOVY_HOME%). 它会在类似Unix的系统上产生预期的输出(在Windows上,您需要用分号替换冒号,变量访问将类似于%GROOVY_HOME%)。

The reason is quite simple: Groovy produces for groovy main methods not the same signature as required by the java specification. 原因很简单:Groovy为groovy主方法生成的签名与Java规范要求的签名不同。 Therefore, you can only invoke a groovy main with groovy on the CLASSPATH - what makes totally sense! 因此,您只能在CLASSPATH上使用groovy调用groovy main-完全有道理!

You can check this for yourself. 您可以自己检查。 Try now the command: 现在尝试命令:

javap Main.class

This will give you a quick analysis of the bytecode and the present interfaces of the class "Main.class". 这将使您对字节码和“ Main.class”类的当前接口进行快速分析。 All along you will see something similar to this output: 一直以来,您将看到类似于以下输出的内容:

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);
}

Of interest is line 5: 有趣的是第5行:

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

This seems quite similar to a normal java main, but with one difference: groovyc used an java.lang.String ellipsis (as stated by the three dots) and not and java.lang.String[]. 这似乎与普通的Java主程序非常相似,但有一个区别:groovyc使用java.lang.String省略号(如三个点所示),而不使用java.lang.String []。

So this could be the reason. 因此,这可能是原因。 I'm not so sure, because normally java will give you an appropriate error output if it can find the class but not the method signature. 我不太确定,因为通常Java如果可以找到类但不能找到方法签名,则会为您提供适当的错误输出。 For example, try: 例如,尝试:

java java.lang.Integer

which has clearly not a main method. 这显然不是主要方法。 Java sees that correctly: 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

I'm also not sure, what groovy does during class loading for understanding this kind of main signature (or lets says this kind of bytecode), but if you compare that with a normal java hello world javap output, you get 我也不确定,在类加载过程中如何使用groovy来理解这种主要签名(或者让我们说这种字节码),但是如果将其与普通的java hello world javap输出进行比较,则会得到

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

which has a different and the normal java main signature. 与正常的Java主签名不同。

Maybe someone from the pivotal groovy team can clarify. 至关重要的团队成员可以澄清一下。 I hope this will give you a hint. 我希望这会给您提示。

The test2.class needs to be on your CLASSPATH. test2.class必须在您的CLASSPATH上。 For example, if it is at /Users/you/classes/test2.class then /Users/you/classes/ needs to be on your CLASSPATH. 例如,如果它位于/Users/you/classes/test2.class,则/ Users / you / classes /必须位于CLASSPATH上。

Since you are building with Gradle, you could also just let Gradle sort all of that out for you using JavaExec. 由于使用Gradle进行构建,因此您也可以使用JavaExec让Gradle为您解决所有问题。 See http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html for more info. 有关更多信息,请参见http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html A simple example in your build.gradle might be something like this: 您的build.gradle中的一个简单示例可能是这样的:

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

I hope that helps. 希望对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM