我有一个简单的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 也不起作用(文件位于正确的位置)。
答案 0 :(得分:11)
我知道这对于OP来说可能有点晚了但是:
鉴于您的groovy main存在,错误消息:
错误:无法找到或加载主类YOUR_MAINCLASS_HERE
来自 java 命令执行groovy main (生成类的已编译groovy文件)基本上意味着你的 groovy jar 是不在类路径 。
更长的答案:
让我们看看为什么这是一个简单的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.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输出进行比较,你会得到< / p>
public class JMain {
public JMain();
public static void main(java.lang.String[]);
}
具有不同的普通java主签名。
也许来自关键的常规团队的人可以澄清。 我希望这会给你一个提示。
答案 1 :(得分: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
}
我希望有所帮助。