6

次のantタスクを使用して、クリーンなディレクトリ(インクリメンタルコンパイルなし)からさまざまなパッケージから100を超えるJavaクラスをコンパイルしようとしています。

<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を使用して自動デイリービルドを実行しているため、これは望ましくありません。これにより、誤ったビルドエラーが発生します。

迅速で汚い解決策として、私は2つの別々のタスクを作成し、それぞれでプロジェクトの一部をコンパイルしました。将来的にクラスが追加されるため、このソリューションが有効になるとは思いません。また、「コンパイル制限」に達するたびに新しいコンパイルタスクを追加したくありません。

4

7 に答える 7

5

知っておくと便利です。Java コードのコンパイル中に StackOverflowError が発生する原因は何ですか?

Java ファイルの長い式を評価すると大量のメモリが消費される可能性があります。これは他のクラスのコンパイルと一緒に行われるため、VM はスタック領域を使い果たします。生成されたクラスは、そのコンテンツの法的な制限を押し広げている可能性があります。The Java Virtual Machine Specification, Second Editionの章4.10 Java Virtual Machine の制限を参照してください。

修正 1: クラスをリファクタリングする

クラスが生成されているため、これはオプションではない可能性があります。それでも、クラス生成ツールが提供するオプションを調べて、問題の少ないものを生成できるかどうかを確認することは価値があります。

修正 2: スタック サイズを増やす

Kieronが -Xss 引数について言及したとき、1 つの解決策があると思います。javacは、バージョンやコンパイラ ベンダーによって異なる多数の非標準引数を取ります。

私のコンパイラ:

$ javac -version
javac 1.6.0_05

すべてのオプションを一覧表示するには、次のコマンドを使用します。

javac -help
javac -X
javac -J-X

javac のスタック制限はデフォルトで 512Kbだと思います。次のコマンドを使用して、このコンパイラのスタック サイズを 10Mb に増やすことができます。

javac -J-Xss10M Foo.java

javacタスクにネストされたcompilerarg要素を使用して、これを Ant ファイルに渡すことができる場合があります。

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J-Xss10M" />
</javac>
于 2008-08-21T12:58:37.930 に答える
3
  <javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
      <compilerarg value="-J-Xss10M" />
    </javac>

上記のコメントからは正しくありません。次のように、-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

于 2009-06-25T04:50:34.720 に答える
1

これは、コマンドラインからjavacコマンドを実行したときに発生しますか?fork属性を試してみることをお勧めします。

于 2008-08-19T21:04:42.723 に答える
1

これらの属性のバリエーションをAntjavacタスクラインに追加してみてください。

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

スタックとヒープ(別名-Xm1024)の値を設定できるかどうかわからない場合も試してみることがfork="true"できますが、役立つ場合があります(コマンドラインからは機能するが、Antでは機能しない場合)。

[編集]:リンクを追加しました-javacタスクページは、上記のパラメータでも設定する必要があることを示唆しているようですfork="true"

于 2008-08-19T21:05:28.010 に答える
0

100 クラスは実際にはそれほど多くありません。スタックがオーバーフローしたとき、コンパイラは何をしていますか? 有用なスタック トレースが生成されていますか? javacスルー ant ではなく、コマンド ラインで直接実行するとどうなりますか?

-Xss考えられる回避策の 1 つは、JVM への引数を使用してスタックのサイズを単純に増やすことです。実行中の JVM に接続するか、タスクにと aをant設定します。実は今考えてみると、 を入れるだけで問題は解決するのでしょうか?fork="true"<compilerarg><javac>fork="true"

于 2008-08-19T21:21:16.607 に答える
0

これが私が見つけたものです。質問を投稿した後、コンパイル タスクを属性fork="true", memoryinitialsize="256m"andで変更しmemorymaximumsize="1024m"ました (今日、これは Kieron と jmanning2k によって提案されたことがわかりました。お時間をいただきありがとうございます)。それでも問題は解決しませんでした。

問題を特定できるかどうかを確認するために、ソース ツリーからクラスを削除することにしました。WSDL ファイルから自動生成されたAxis 1.4用の Web サービス クライアント クラスがあったことがわかりました。現在、このクラスはモンスター (フランケンシュタインのように) であり、167 のフィールド メンバー (すべて String 型)、167 のゲッター/セッターのペア (フィールドごとに 1 つ)、167 のフィールドすべてをパラメーターとして受け取るコンストラクター、奇妙な方法で 167 フィールドすべてを比較する equals メソッド。各フィールドの比較は次のようになります。

(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
于 2008-08-20T14:23:06.457 に答える
0

他の回答のいくつかは、設定​​が必要な修正について言及していますが、別のオプションは、環境変数fork="true"を設定することにより、ant によって作成された基盤となる JVM のスタック領域を増やすことです。ANT_OPTS

ANT_OPTS=-Xss10M ant
于 2021-04-05T19:02:30.063 に答える