2008-08-19 60 views
4

我試圖使用以下Ant任務乾淨 目錄(無增量編譯)彙編從不同的包超過100個Java類:Ant的<javac>任務拋出StackOverflowException

<target name="-main-src-depend"> 
    <depend srcdir="${src.dir}" 
      destdir="${bin.dir}" 
      cache="${cache.dir}" 
      closure="true"/> 
</target> 

<target name="compile" depends="-main-src-depend" 
     description="Compiles the project."> 

    <echo>Compiling</echo> 

    <javac target="${javac.target}" 
      source="${javac.source}" 
      debug="${javac.debug}" 
      srcdir="${src.dir}" 
      destdir="${bin.dir}"> 
     <classpath> 
      <path refid="runtime.classpath"/> 
      <path refid="compile.classpath"/> 
     </classpath> 
    </javac> 
</target> 

但是,我第一次運行編譯任務我總是得到一個StackOverflowException。如果我再次運行該任務,編譯器會執行增量構建,並且一切正常。這是不受歡迎的,因爲我們使用CruiseControl來進行自動日常構建,這會導致構建失敗失敗。

作爲一種快速而骯髒的解決方案,我創建了兩個獨立的任務,分別編譯項目的各個部分。我真的不認爲這個解決方案會成功,因爲將來會增加更多的類,並且我不希望每次達到「編譯限制」時都要增加新的編譯任務。

+1

它拋出一個StackOverflowException - 所以你來責怪我們? :-) – kenj0418 2009-06-25 05:10:55

+0

@ kenj0418 - 你的評論真的讓我撓我的腦袋,直到我看到笑臉。好的! – 2009-06-25 18:18:19

回答

4

It will be nice to know; what can cause or causes a StackOverflowError during compilation of Java code?

這是可能的評估在長期的表達你的java文件會佔用大量的內存,並且因爲這是與其他類的編譯一起完成的,所以VM只是運行超出堆棧空間。您生成的課程可能會推動其內容的法定限制。參見The Java Virtual Machine Specification, Second Edition中的章節4.10 Limitations of the Java Virtual Machine

修復1:重構類

由於正在生成類,這可能不是一個選項。儘管如此,還是值得看看你的班級生成工具提供的選項,看看它是否可以減少麻煩。

修復2:增加堆棧大小

我認爲Kieron有一個解決方案時,他提到了-Xss參數。 javac需要許多不同版本和編譯器供應商之間不同的非標準參數。

我的編譯器:

$ javac -version 
javac 1.6.0_05 

要列出它的所有選擇,我會使用以下命令:

javac -help 
javac -X 
javac -J-X 

認爲爲javac堆棧限制爲512KB默認。您可以使用此命令增加堆棧大小爲這個編譯器爲10Mb:

javac -J-Xss10M Foo.java 

您可能能夠在Ant文件,嵌套在的javac任務compilerarg元素通過這一點。

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true"> 
    <compilerarg value="-J-Xss10M" /> 
</javac> 
1

當您從命令行運行javac命令時會發生這種情況嗎?您可能想要嘗試fork屬性。

1

嘗試增加這些屬性的某種變體的Ant javac task行:

memoryinitialsize="256M" memorymaximumsize="1024M" 

您也可以嘗試fork="true",不知道這是否允許你設置棧和堆(又名-Xm1024)值,但它可能會有幫助(如果它可以從命令行,但不在Ant中)。

[編輯]: 新增環節 - javac task頁面似乎表明,上面的參數要求,你還設置fork="true"

0

這很奇怪,100班真的沒有那麼多。編譯器在堆棧溢出時做什麼?有沒有生成有用的堆棧跟蹤?如果直接在命令行上運行javac而不是直接運行,會發生什麼情況?

一種可能的解決方法是使用-Xss參數簡單地增加JVM的堆棧大小;或者運行ant的JVM或和<compilerarg><javac>任務。事實上,現在我想到了,問題是否只是放入fork="true"

0

這是我發現的。 發佈我的問題後,我繼續並修改了屬性fork="true",memoryinitialsize="256m"memorymaximumsize="1024m"(今天發現這是由Kieron和jmanning2k提供的,感謝您的時間)的編譯任務。儘管如此,這並沒有解決問題。

我決定開始從源代碼樹中刪除類,看看是否可以查明問題。事實證明,我們有一個從WSDL文件自動生成的Axis 1.4 Web服務客戶端類。現在,這個類是一個怪物(如在Frankenstein中),它有167個字段成員(都是String類型),167個getter/setter對(每個字段爲1),一個接收所有167個字段作爲參數的構造函數,等於以奇怪的方式比較所有167個字段的方法。每個字段的比較是這樣的:

(this.A == null && other.getA() == null) || (this.A != null && this.A.equals(other.getA())) 

該比較的結果是「相與」(& &)與下一個場的比較,等等的結果。該類繼續使用一個也使用所有字段的hashCode方法,一些自定義XML序列化方法和一個方法,該方法返回一個Axis特定的元數據對象,該元數據對象描述類並且也使用所有字段成員。

這個類永遠不會被修改,所以我只是把一個編譯好的版本放在應用程序類路徑中,並且編譯的項目沒有問題。

現在,我知道刪除這個單一的源文件解決了這個問題。不過,我完全不知道爲什麼這個班級造成這個問題。很高興知道;在編譯Java代碼的過程中會導致或導致StackOverflowError的原因是什麼?我想我會提出這個問題。

對於那些有興趣:

  • 的Windows XP SP2
  • Sun的JDK 1.4.2_17
  • 螞蟻1.7.0
1
<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true"> 
     <compilerarg value="-J-Xss10M" /> 
    </javac> 

comment above不正確。您需要-J和-X之間的空間,像這樣:

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true"> 
    <compilerarg value="-J -Xss10M" /> 
</javac> 

避免以下錯誤:

[javac] 
[javac] The ' characters around the executable and arguments are 
[javac] not part of the command. 
[javac] Files to be compiled: 

... [javac的]的javac:無效的標誌:-J- Xss1m [javac]用法:javac