2008-08-19 86 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