简体   繁体   中英

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

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

I assuming I need to add asm and groovy to the class path. 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).

I know this may be a bit late for the OP but nevertheless:

Given that your groovy main exists, the error message:

Error: Could not find or load main class 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 .

Longer Answer:

Lets see why that is for a simple hello world example. I have a file called main.groovy with the following content:

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.

In the command prompt, compile the file with groovyc , so just type in:

groovyc main.groovy

This will produce a file called M ain.class (with uppercase M because of the class name).

Ok now we have the appropriate test setup. If you now try to run the file just with java command:

java Main 

you will get the error message:

Error: Could not find or load main class 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.

In contrast, try again with groovy in your classpath. I will refer to the directory of your groovy installation as GROOVY_HOME. To run the hello world Main class finally, we can type in:

java -cp ".:/$GROOVY_HOME/lib/*" Main

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%).

The reason is quite simple: Groovy produces for groovy main methods not the same signature as required by the java specification. Therefore, you can only invoke a groovy main with groovy on the CLASSPATH - what makes totally sense!

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". 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:

  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[].

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. For example, try:

java java.lang.Integer

which has clearly not a main method. Java sees that correctly:

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

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

which has a different and the normal java main signature.

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. For example, if it is at /Users/you/classes/test2.class then /Users/you/classes/ needs to be on your CLASSPATH.

Since you are building with Gradle, you could also just let Gradle sort all of that out for you using JavaExec. See http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html for more info. A simple example in your build.gradle might be something like this:

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

I hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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