2013-04-17 5 views
2

когда я запускаю ниже программон должен быть StackOverflowError или OOME

class Person{ 
    Person p; 
    Person(){ 
     System.out.println("Hi"); 
     p = new Person(); 
    } 
} 

public class Main { 


    public static void main(String[] args) { 
     new Person(); 
    } 
} 

он бросает StackOverflow ошибки , но я ожидал, что это будет OOME, как мы работаем с созданием объекта, а не с каким-либо локальным методом/переменным или задающее

+0

Похоже, вы пытаетесь создать объект person в конструкторе класса person и, похоже, вы входите в бесконечный цикл. – jpw

ответ

4

Вы рекурсивны и без условия завершения вызывающего Person() конструктора, который помещает данные в стеке (по крайней мере, обратный адрес - стек используются не только для локальных переменных и параметров):

Person(){ 
    p = new Person(); // <<== Calls the Person() constructor, which again calls the Person() constructor, which again ... 
} 

Следовательно, вы получаете ошибку переполнения стека.

Теоретически компилятор мог видеть, что это хвостовая рекурсия и оптимизация вызова метода, но этого не происходит.

В самой куче создаются объекты Person, но обычно куча больше, чем стек (по крайней мере, по умолчанию), поэтому стек заполняется раньше кучи.

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

java -Xss128M -Xmx4M Person 

и вы получите OOME вместо переполнения стека.

+0

Конструктор помещает данные в кучу, поскольку ее часть создания объекта (которая существует в куче), не так ли? –

+0

Сам объект создается в куче 'new', но все же вызов конструктора помещает по крайней мере обратный адрес в стек. Обычно куча больше, чем стек, поэтому стек заполняется до кучи. –

0

Причина рекурсия-ПРИВЛЕЧЕНИЕ произошло в конструктор по умолчанию Person().

На более глубоком уровне знаний JVM, чтобы объяснить эту проблему: виртуальная Java спецификация машина правили две ситуации исключения для стека Java:

  1. стек Java это позволило расширить автоматически, он будет бросать Ошибка OOM (OutOfMemory), когда она не может применяться для достаточной памяти.
  2. Стек Java состоит из фрейма стека, и каждый метод java нажимает рамку, он выкинет StackOverflowError, когда стек глубина текущего потока больше разрешенного jvm.

Может помочь вам :)

2

Ваши ожидания не необоснованное.

Есть две силы на работе здесь: создание

  • Объект человека() в куче
  • CallStack расширение с помощью глубокой рекурсии

Какой один из этих 2 терпит неудачу первой является anyones догадываться, и сильно зависит от настроек JVM. Установите свой -Xmx в очень низкое значение, и вы, скорее всего, сначала получите OOMException.

+0

Расширение Callstack посредством глубокой рекурсии - означает, что рекурсия будет происходить на Stack вообще. –

Смежные вопросы