Javaで記述したプログラムを実行しています。プログラムには、非常に大きな入力に対して非常に深いレベルの再帰があります。与えられた、私は次のエラーが表示されます:
Exception in thread "main" Java.lang.StackOverflowError
これは、Javaスタックサイズを増やすことで解決できますか?
更新:
@ジョン・スキート
コードは、データ構造を構築するために、解析ツリーを再帰的に走査します。したがって、たとえば、コードは解析ツリーのノードを使用していくつかの作業を行い、ノードの2つの子でそれ自体を呼び出し、その結果を組み合わせてツリーの全体的な結果を提供します。
再帰の合計の深さは解析ツリーのサイズに依存しますが、再帰呼び出しの数が1000に達すると、コードは(より大きなスタックなしで)失敗するようです。
また、小さな入力でも機能するため、バグが原因でコードが失敗することはないと確信しています。
アプリケーションのRun Configurationを開きます(Run/Run Configurations ...、次に 'Java application'でアプリケーションエントリを探します)。
argumentsタブにはテキストボックスがありますVm arguments、enter -Xss1m
(または最大スタックサイズのより大きなパラメーター)。デフォルト値は512 kByteです(Sun JDK 1.5-ベンダーとバージョンによって異なるかどうかはわかりません)。
それはmayスタックサイズを増やすことで回復可能ですが、betterの解決策は、それほど再帰を避ける方法を見つけることです。再帰的なソリューションは、常に反復的なソリューションに変換できます。これにより、コードがより大きな入力にはるかにきれいにスケールされます。それ以外の場合は、提供するスタックの量を実際に推測しますが、これは入力からも明らかではない場合があります。
ちなみに、コードのバグではなく、入力のサイズが原因で失敗していると確信していますか?この再帰の深さは?
編集:さて、更新を見たので、私は個人的に再帰を使用しないようにそれを書き直そうとします。通常、Stack<T>
の「まだやること」は、再帰を削除するための良い出発点です。
VM引数)にフラグ-Xss1024k
を追加します。
たとえば-Xss1m
を使用して、mb
のスタックサイズを増やすこともできます。
xSOMライブラリを使用してスキーマ定義ファイル(XSD)を解析しているときにも同じ問題があります
スタックメモリを最大208Mbまで増やすことができた後、heap_out_of_memory_error
私は320MBまでしか増やすことができませんでした。
最終構成は-Xmx320m -Xss208m
しかし、再びそれはしばらく実行され、失敗しました。
私の関数は、スキーマ定義のツリー全体を再帰的に出力します。出力ファイルは、4MB(Aixmライブラリ)の定義ファイルで820MBを超え、スキーマ定義ライブラリ(ISO gml)を50MB使用します。
それで、再帰を避けてから、反復および出力を表す他の方法を開始する必要があると確信していますが、すべての再帰を反復に変換するのに問題はほとんどありません。
JVMパラメーターを調整するには、Eclipse内に起動構成が必要です。
F11またはCtrl-F11でプログラムを実行した後、実行->実行構成...で起動構成を開き、「Javaアプリケーション」の下でプログラムを開きます。 「VM引数」がある「引数」ペインを選択します。
これは-Xss1024k
行く。
起動構成をワークスペース内のファイルにする場合(右クリックして実行できるようにするため)、(共通)ペインを選択し、(名前を付けて保存)->(共有ファイル)チェックボックスをオンにして、起動ファイルが必要な場所を参照します。それらをCVSにチェックインするとき、私は通常それらを別のフォルダーに入れます。
引数-Xss
は、次の場所から一時ファイルを削除しようとしません。
c:\Users\{user}\AppData\Local\Temp\.
これは私のためにトリックをしました。
一定のスペースを使用し、O(n)(通常の再帰トラバーサルよりも最大3倍長くなりますが、スペースを大幅に節約します)。ノードを変更できます。ルートにバックトラックするときにサブノードの計算結果を保存できます(ノードに直接書き込むことにより)。