Что происходит при переполнении стека, например при бесконечной рекурсии?
Что проверяют
Понимаете ли вы, как устроена память потока в JVM и чем стек отличается от кучи. Следом часто спрашивают, можно ли поймать StackOverflowError, стоит ли это делать и помогает ли увеличение -Xss.
Как отвечать
У каждого потока свой стек. На каждый вызов метода в нём создаётся фрейм: локальные переменные, стек операндов, адрес возврата. Размер стека фиксируется при создании потока: флагом -Xss (на 64-битных Linux и macOS по умолчанию 1 МБ) или параметром stackSize в конструкторе Thread, который JVM вправе проигнорировать.
Когда очередной фрейм не помещается, HotSpot замечает это по защитным страницам в конце стека и бросает StackOverflowError. Детали, которые стоит назвать:
- это
Error, а неException: наследникVirtualMachineError, поэтомуcatch (Exception e)его не поймает; - падает поток, а не JVM: стек разматывается, блоки
finallyвыполняются. Если ошибку никто не поймал, поток завершается, а процесс живёт, пока есть другие не-daemon потоки; - глубина не константа: она зависит от размера фреймов, а JIT-скомпилированный код расходует стек иначе, чем интерпретатор, поэтому одна и та же рекурсия падает на разной глубине;
- оптимизации хвостовой рекурсии в JVM нет: глубокий обход переписывают на цикл с явным
ArrayDeque.
Сильный ответ добавит случаи из жизни, а не только учебный метод без выхода. Это toString(), equals() и hashCode() на двунаправленных JPA-сущностях, особенно с Lombok @Data на обеих сторонах, и сериализация таких связей в Jackson, которую лечат через @JsonManagedReference и @JsonBackReference или через DTO.
Где спотыкаются
Называют это исключением и предлагают обернуть вызов в try/catch. Поймать StackOverflowError можно, но состояние программы после него ненадёжно: какая-то операция оборвалась на середине.
Считают -Xss решением. Бесконечную рекурсию больший стек не спасает, он лишь откладывает падение и увеличивает резерв памяти под каждый поток.
Путают с OutOfMemoryError. Куча и стек это разные области, и переполнение стека никак не связано с -Xmx.