Ошибка переполнения стека Java – как увеличить размер стека в Eclipse?

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

Exception in thread "main" java.lang.StackOverflowError

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

Обновление:

@Джон Скит

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

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

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


person tree-hacker    schedule 24.01.2010    source источник
comment
что-то здесь не так... stackoverflow(.com) не является ошибкой! :-)   -  person user85421    schedule 24.01.2010
comment
@CarlosHeuberger, ты забавный братан!   -  person HendraWD    schedule 27.06.2019
comment
@HendraWD 9 лет назад я был ребенком - не совсем [:-)   -  person user85421    schedule 27.06.2019


Ответы (8)


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

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

person Andreas Dolk    schedule 24.01.2010
comment
Помните об этой проблеме: bugs.sun.com/bugdatabase/view_bug.do? bug_id=6316197 - person Jim Rush; 24.01.2010

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

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

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

person Jon Skeet    schedule 24.01.2010
comment
Я не могу вспомнить состояние хвостовой рекурсии на jvms. Cue комментарий от tackline. - person Jon Skeet; 24.01.2010
comment
JVM, как правило, еще не оптимизируют хвостовые рекурсии. Я считаю, что это одна из вещей, которую должно исправить обобщение JVM на языки, отличные от Java. - person Thorbjørn Ravn Andersen; 24.01.2010
comment
Я обновил вопрос в ответ на вопросы Джона Скита. - person tree-hacker; 25.01.2010
comment
По сути, пространство стека — это память, такая же, как куча. Почему лучше использовать кучу? Это зависит от вашего приложения и того, как вы решаете свои проблемы. Бывают ситуации, когда управление памятью более эффективно при использовании стека, а не кучи. Есть также ситуации, когда алгоритмы на основе стека более лаконичны; например парсеры. - person ziggystar; 18.03.2012
comment
@ziggystar Куча лучше, потому что она больше. Ответ на вопрос, почему стек такой маленький, можно найти здесь: stackoverflow.com/questions/10482974. Я согласен, что рекурсия часто более лаконична и ясна. Но когда нельзя предположить каких-либо ограничений на глубину рекурсии, безопаснее отменить рекурсию, как предлагает Джон Скит. Ведь стек как структура данных в языке программирования и стек как часть памяти не зря называются одинаково. - person pepan; 11.10.2013

Добавьте флаг -Xss1024k в аргументы виртуальной машины.

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

person Gordon    schedule 24.01.2010

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

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

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

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

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

person Ratnakar    schedule 09.03.2011

Вам нужно иметь конфигурацию запуска внутри Eclipse, чтобы настроить параметры JVM.

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

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

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

person Thorbjørn Ravn Andersen    schedule 24.01.2010

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

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

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

person ticu0000    schedule 17.07.2013

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

person Maria Sakharova    schedule 27.02.2015

При использовании JBOSS Server дважды щелкните сервер:

введите здесь описание изображения

Перейдите в раздел Открыть конфигурацию запуска.

введите здесь описание изображения

Затем измените min и max размеры памяти (например, 1G, 1M):

введите здесь описание изображения

person Matheus Santz    schedule 04.09.2020