2014-10-02 58 views
1

我有一個簡單的常規文件,如下所示:使用java運行javac編譯的groovy代碼?

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

我gradle這個任務被編譯成一個test2的類文件

如何運行從提示這個文件呢?

的Java測試2(從test2.class文件的位置) 導致:錯誤:無法找到或加載主類test2.class

我假設我需要ASM和常規添加到班級路徑。但是: java -cp「groovy-all-2.3.6.jar; asm-all-3.3.1.jar」test2 也不起作用(文件位於正確的位置)。

回答

10

我知道這可能是有點晚了OP但儘管如​​此:

考慮到你的Groovy主要存在的錯誤信息:在執行

Error: Could not find or load main class YOUR_MAINCLASS_HERE

的java命令groovy主(生產類編譯的groovy文件)基本上意味着你的groovy jar不在classp ath

再回應:

讓我們來看看爲什麼這是一個簡單的Hello World例子。我有一個名爲main.groovy,內容如下文件:

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

}

把這個地方在你的文件系統。在相同的目錄中打開命令提示符,並確保groovy和java可通過PATH訪問。

在命令提示符下,編譯groovyc的文件,所以只需要輸入:由於類名的

groovyc main.groovy 

這將產生一個名爲中號 ain.class(用大寫字母M )。

好了,現在我們有適當的測試設置。如果您現在嘗試運行該文件只是用java命令:

java Main 

您將收到錯誤消息:

Error: Could not find or load main class Main

這是一個有點意外,因爲人能想到,我們只是可以調用主要在我們的Main.class中,而沒有鏈接groovy庫,所以我們會期望像ClassNotFoundException這樣的異常。

相反,請在類路徑中再次使用groovy。我將把你的groovy安裝目錄稱爲GROOVY_HOME。爲了最終運行Hello World主類,我們可以輸入:

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爲主,但有一點不同:groovyc的使用的Java .lang.String省略號(如三點說明)和not和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 

我也不能確定,類加載過程中所做的常規理解這種主要的簽名(或讓說,這種字節碼),但如果你比較,與正常Java的世界你好javap的輸出,你

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

具有不同與普通的Java的主要特徵。

也許有人來自關鍵時髦團隊可以澄清。 我希望這會給你一個提示。

+0

很棒的回答。謝謝。 – 2017-09-22 11:35:41

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 
} 

我希望有幫助。

+0

我從包含test2.class的目錄運行它,而test2沒有包定義。 – vicsz 2014-10-02 18:14:17

+0

然後將當前目錄放在您的CLASSPATH上。 – 2014-10-02 18:16:33

+1

使用「。」。 'java -cp「groovy-all-2.3.6.jar; asm-all-3.3.1.jar ;.」 test2' – 2014-10-02 18:17:21

相關問題