2010-01-24 25 views
55

Używam programu, który napisałem w Javie w środowisku Eclipse. Program ma bardzo głęboki poziom rekurencji dla bardzo dużych wejść. W przypadku mniejszych nakładów program działa w porządku, jednak gdy podane są duże nakłady, pojawia się następujący błąd:Błąd przepełnienia stosu Java - jak zwiększyć rozmiar stosu w Eclipse?

Exception in thread "main" java.lang.StackOverflowError 

można to rozwiązać przez zwiększenie rozmiaru stosu Java, a jeśli tak, to w jaki sposób mogę to zrobić w Eclipse?

Aktualizacja:

@Jon Skeet

Kod jest przejeżdżające drzewo parsującej rekurencyjnie, aby zbudować datastructure. Tak więc, na przykład, kod będzie działał przy użyciu węzła w drzewie analizy i wywołuje się na dwójce dzieci węzła, łącząc ich wyniki, aby uzyskać ogólny wynik dla drzewa.

Całkowita głębokość rekursji zależy od wielkości drzewa analizy, ale kod wydaje się nie udać (bez większego stosu), gdy liczba wywołań rekursywnych dostaje się do 1000.

Jestem również pewien, że kod nie zawodzi z powodu błędu, ponieważ działa on dla małych wejść.

+7

coś tu nie tak ... stackoverflow (.com) nie jest błędem! :-) –

Odpowiedz

72

Otwórz konfigurację Run dla swojej aplikacji (Run/Run Configurations ..., a następnie poszukaj wpisu aplikacji w "aplikacji Java").

argumenty zakładka ma pole tekstowe Vm argumenty, wprowadź -Xss1m (lub większy parametr maksymalny rozmiar stosu). Domyślna wartość to 512 kBajtów (SUN JDK 1.5 - nie wiem, czy jest ona różna dla różnych dostawców i wersji).

+2

Należy pamiętać o tym problemie: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6316197 –

10

Dodaj flagę -Xss1024k w Argumenty maszyny wirtualnej.

Możesz także zwiększyć rozmiar stosu w mb, używając np. -Xss1m.

37

To może być uleczalna zwiększając rozmiar stosu - ale lepiej rozwiązaniem byłoby dowiedzieć się, jak uniknąć recursing tyle. Rozwiązanie rekursywne zawsze można przekonwertować na rozwiązanie iteracyjne - co sprawi, że twój kod skaluje się na większe wejścia o wiele bardziej czysto. W przeciwnym razie naprawdę będziesz zgadywał, ile stosu dostarczyć, co może nie być nawet oczywiste z danych wejściowych.

Jesteś pewny, że to błąd z powodu rozmiaru wejścia, a nie błędu w kodzie? Jak głęboka jest ta rekurencja?

EDYCJA: Okay, widząc aktualizację, osobiście spróbowałbym przepisać go, aby uniknąć używania rekursji. Ogólnie rzecz biorąc posiadanie Stack<T> "rzeczy, które wciąż trzeba zrobić" jest dobrym punktem wyjścia do usunięcia rekursji.

+4

.. lub przez rekursję ogona. – BalusC

+0

Nie pamiętam stanu rekurencji ogona na jvms. Cue comment from tackline. –

+1

JVM jeszcze nie z reguły optymalizują rekursje ogona. Uważam, że jest to jedna z rzeczy, które należy rozwiązać, aby uogólnić JVM na języki inne niż Java. –

3

Musisz mieć konfigurację uruchamiania wewnątrz Eclipse, aby dostosować parametry maszyny JVM.

Po uruchomieniu programu z F11 lub Ctrl-F11, otwórz konfiguracje uruchamiania w Run -> Run Configurations ... i otwórz program w "Java Applications". Wybierz panel Argumenty, w którym znajdziesz "argumenty VM".

Tutaj następuje -Xss1024k.

Jeśli chcesz, aby konfiguracja uruchamiania była plikiem w twoim obszarze roboczym (możesz kliknąć prawym przyciskiem i uruchomić), wybierz panel Wspólny i zaznacz pole wyboru Zapisz jako -> Plik udostępniony i przejdź do żądanej lokalizacji plik uruchamiania. Zwykle mam je w osobnym folderze, ponieważ sprawdzamy je w CVS.

5

mam również ten sam problem podczas parsowania plików definicji schematu (XSD) przy użyciu biblioteki XSOM,

byłem w stanie zwiększyć pamięć stosu zapisu do 208Mb następnie pokazał to heap_out_of_memory_error dla których udało mi się zwiększyć tylko zapisu do 320MB.

Ostateczna konfiguracja była -Xmx320m -Xss208m, ale potem znowu działała przez jakiś czas i nie powiodła się.

Moja funkcja drukuje rekurencyjnie całe drzewo definicji schematu, co zaskakujące, plik wyjściowy przekroczył 820 MB dla pliku definicji o wielkości 4 Mb (biblioteka Aixm), który z kolei wykorzystuje 50 MB biblioteki definicji schematu (ISO gml).

z tym jestem przekonany, że muszę uniknąć Recursion, a następnie rozpocząć iterację i inny sposób reprezentowania wyjścia, ale mam małe problemy konwersji wszystkich tej rekursji do iteracji.

2

Gdy argument -Xss nie robi praca spróbuj usunąć pliki tymczasowe z:

c:\Users\{user}\AppData\Local\Temp\. 

To załatwiło sprawę dla mnie.

0

Spójrz na przemierzanie drzewa Morris, które korzysta ze stałej przestrzeni i działa w O (n) (do 3 razy dłużej niż zwykłe traursowe przemierzanie - ale oszczędzasz bardzo dużo miejsca). Jeśli węzły są modyfikowalne, możesz zapisać wynik obliczenia pod-drzewa, cofając się do jego katalogu głównego (pisząc bezpośrednio do węzła).

Powiązane problemy