62

Java で作成したプログラムを Eclipse で実行しています。プログラムには、非常に大きな入力に対して非常に深いレベルの再帰があります。小さい入力の場合、プログラムは正常に実行されますが、大きな入力が与えられると、次のエラーが発生します。

Exception in thread "main" java.lang.StackOverflowError

Javaスタックサイズを増やすことでこれを解決できますか?もしそうなら、Eclipseでこれを行うにはどうすればよいですか?

アップデート:

@ジョン・スキート

コードは、データ構造を構築するために解析ツリーを再帰的にトラバースしています。したがって、たとえば、コードは解析ツリー内のノードを使用していくつかの作業を行い、ノードの 2 つの子でそれ自体を呼び出し、それらの結果を組み合わせてツリーの全体的な結果を提供します。

再帰の合計の深さは解析ツリーのサイズによって異なりますが、再帰呼び出しの数が 1000 に達すると、コードは (より大きなスタックなしで) 失敗するように見えます。

また、小さな入力でも機能するため、バグが原因でコードが失敗することはないと確信しています。

4

8 に答える 8

83

アプリケーションの実行構成を開きます (実行/実行構成... を開き、「Java アプリケーション」でアプリケーション エントリを探します)。

引数タブには、テキスト ボックスVm 引数、入力-Xss1m(または最大スタック サイズのより大きなパラメーター) があります。デフォルト値は 512 kByte です (SUN JDK 1.5 - ベンダーやバージョンによって異なるかどうかは不明です)。

于 2010-01-24T13:52:20.570 に答える
38

スタックサイズを大きくすることで解決できるかもしれませんが、より良い解決策は、再帰をあまり避ける方法を考えることです。再帰的な解決策は常に反復的な解決策に変換できます。これにより、コードがより大きな入力に対してよりきれいにスケーリングされます。そうしないと、提供するスタックの量を実際に推測することになり、入力からは明らかではない場合があります。

ところで、コードのバグではなく、入力のサイズが原因で失敗していると確信していますか? この再帰はどのくらい深いのでしょうか?

編集:さて、更新を見たので、再帰の使用を避けるために個人的に書き直そうとします。一般に、Stack<T>再帰を削除するための出発点として、「まだ行うべきこと」を設定することが適切です。

于 2010-01-24T13:40:02.507 に答える
10

-Xss1024kVM 引数にフラグを追加します。

たとえばmbを使用して、スタック サイズを増やすこともできます。-Xss1m

于 2010-01-24T13:39:15.917 に答える
5

XSOM ライブラリを使用してスキーマ定義ファイル (XSD) を解析しているときにも同じ問題が発生します。

スタック メモリを 208Mb まで増やすことheap_out_of_memory_errorができましたが、320MB までしか増やすことができなかったことが示されました。

最終的な構成はできました-Xmx320m -Xss208mが、しばらく実行して失敗しました。

私の関数は、スキーマ定義のツリー全体を再帰的に出力します。驚くべきことに、出力ファイルは、4 Mb の定義ファイル (Aixm ライブラリ) に対して 820 Mb を超え、50 Mb のスキーマ定義ライブラリ (ISO gml) を使用します。

それで、再帰を避けてから反復を開始し、出力を表す他の方法を開始する必要があると確信していますが、そのすべての再帰を反復に変換するのにほとんど問題はありません。

于 2011-03-09T07:43:32.677 に答える
3

JVM パラメーターを調整するには、Eclipse 内に起動構成が必要です。

F11 または Ctrl-F11 を使用してプログラムを実行した後、[実行] -> [実行構成...] で起動構成を開き、[Java アプリケーション] でプログラムを開きます。「VM 引数」がある [引数] ペインを選択します。

これが-Xss1024k行き先です。

起動構成をワークスペース内のファイルにする (右クリックして実行できるようにする) 場合は、[共通] ペインを選択し、[名前を付けて保存] -> [共有ファイル] チェックボックスをオンにして、起動ファイルが必要な場所を参照します。それらを CVS にチェックインするので、通常は別のフォルダに保管します。

于 2010-01-24T13:51:33.057 に答える
0

一定のスペースを使用し、O(n) で実行される Morris の順序ツリー トラバーサルを見てください (通常の再帰トラバーサルよりも最大 3 倍長くなりますが、スペースを大幅に節約できます)。ノードが変更可能な場合は、(ノードに直接書き込むことによって) ルートに戻るときに、サブツリーの計算結果を保存できます。

于 2015-02-27T10:53:01.583 に答える