Ошибка переполнения стека Java - как увеличить размер стека в Eclipse? - PullRequest
57 голосов
/ 24 января 2010

Я запускаю программу, написанную на Java в Eclipse. Программа имеет очень глубокий уровень рекурсии для очень больших входов. Для небольших входных данных программа работает нормально, однако, когда вводятся большие входные данные, я получаю следующую ошибку:

Exception in thread "main" java.lang.StackOverflowError

Можно ли решить эту проблему, увеличив размер стека Java, и если да, то как мне это сделать в Eclipse?

Обновление:

@ Джон Скит

Код рекурсивно перебирает дерево разбора для создания структуры данных. Так, например, код выполнит некоторую работу, используя узел в дереве разбора, и вызовет себя у двух дочерних узлов, объединив их результаты, чтобы получить общий результат для дерева.

Общая глубина рекурсии зависит от размера дерева разбора, но, похоже, код не работает (без большого стека), когда число рекурсивных вызовов достигает 1000.

Также я почти уверен, что код не дает сбоя из-за ошибки, так как он работает для небольших входных данных.

Ответы [ 7 ]

77 голосов
/ 24 января 2010

Откройте Запустить конфигурацию для своего приложения (Запустить / Запустить конфигурации ..., затем найдите запись приложения в «Java-приложении»).

На вкладке arguments есть текстовое поле Vm arguments , введите -Xss1m (или больший параметр для максимального размера стека). Значение по умолчанию - 512 кБайт (SUN JDK 1.5 - не знаю, меняется ли оно между поставщиками и версиями).

37 голосов
/ 24 января 2010

Это может быть излечимым путем увеличения размера стека, но решение лучше состоит в том, чтобы решить, как избежать повторного использования. Рекурсивное решение всегда можно преобразовать в итеративное решение, которое сделает ваш код более масштабным и масштабным для больших входных данных. В противном случае вы действительно догадаетесь, сколько стеков предоставить, что может быть даже неочевидно из входных данных.

Кстати, вы абсолютно уверены, что это происходит из-за размера ввода, а не из-за ошибки в коде? Насколько глубока эта рекурсия?

РЕДАКТИРОВАТЬ: Хорошо, увидев обновление, я лично попытался бы переписать его, чтобы избежать использования рекурсии. Как правило, наличие Stack<T> «вещей, которые все еще делают» является хорошей отправной точкой для удаления рекурсии.

10 голосов
/ 24 января 2010

Добавьте флаг -Xss1024k в Аргументы ВМ.

Вы также можете увеличить размер стека в mb, используя, например, -Xss1m.

5 голосов
/ 09 марта 2011

У меня также есть такая же проблема при разборе файлов определения схемы (XSD) с использованием библиотеки XSOM,

я смог увеличить память стека до 208 МБ, тогда он показал heap_out_of_memory_error, для которого я смог увеличить только до 320 МБ.

окончательная конфигурация была -Xmx320m -Xss208m, но затем она снова работала некоторое время и не удалась.

Моя функция рекурсивно печатает все дерево определения схемы. Удивительно, но выходной файл перешел 820 МБ для файла определения 4 МБ (библиотека Aixm), который в свою очередь использует 50 МБ библиотеки определения схемы (ISO gml).

с этим я убежден, что должен избегать рекурсии, а затем начать итерацию и какой-то другой способ представления выходных данных, но у меня возникли небольшие проблемы с преобразованием всей этой рекурсии в итерацию.

3 голосов
/ 24 января 2010

Для настройки параметров JVM необходима конфигурация запуска в Eclipse.

После запуска вашей программы с помощью F11 или Ctrl-F11 откройте конфигурацию запуска в меню «Выполнить» -> «Выполнить конфигурации» ... и откройте свою программу в разделе «Приложения Java». Выберите панель «Аргументы», где вы найдете «Аргументы виртуальной машины».

Это куда -Xss1024k идет.

Если вы хотите, чтобы конфигурация запуска была файлом в вашей рабочей области (чтобы вы могли щелкнуть правой кнопкой мыши и запустить ее), выберите панель «Общие» и установите флажок «Сохранить как -> Общий файл» и перейдите в нужное место запустить файл. Обычно они хранятся в отдельной папке, поскольку мы регистрируем их в CVS.

2 голосов
/ 17 июля 2013

Если аргумент -Xss не выполняет работу, попробуйте удалить временные файлы из:

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

Это помогло мне.

0 голосов
/ 27 февраля 2015

Посмотрите на обход дерева порядка Морриса, который использует постоянное пространство и работает в O (n) (до 3 раз дольше, чем ваш обычный рекурсивный обход - но вы значительно экономите на пространстве). Если узлы модифицируемы, то вы можете сохранить вычисленный результат поддерева при возврате к его корню (записав непосредственно в узел).

...