Android: увеличение размера стека вызовов

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

интересно, я создал два тестовых примеров:

1) Hello world приложение со следующим xml для основной деятельности

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <!-- ...So on 30 times... -->

                <FrameLayout
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent" >

                </FrameLayout>

            <!-- ...So on 30 times... -->

        </FrameLayout>
    </FrameLayout>
</FrameLayout>

вызывает StackOverflowError при рисовании макета (причина каждого макета рекурсивно рисует его детей)

2) Следующий тест дело

public class TestOverflowActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        overflow(0);
    }

    private void overflow(int i){
        android.util.Log.i("Stack depth:", " = " + i);
        overflow(i+1);
    }
}

причины StackOverflowError на глубину около 260-270 вызовов.

каждый вызов элемента стека для второго тестового случая занимает 4 байта для обратного адреса + 4 bytes для параметра = 8 bytes. Возможно, что Dalvik's VM хранит немного больше информации в каждом элементе, но даже 16 bytes per element * 260 calls = about 4Kbytes для максимального общего размера стека. Это не показалось.

есть ли способ увеличить максимальный размер стека?

3 ответов


возможно, вы не сможете увеличить размер стека вызовов в основном потоке пользовательского интерфейса(что понятно, потому что здесь вы должны делать как можно меньше вещей), но вы можете сделать это в отдельном потоке, используя параметры конструктора объекта Thread:

ThreadGroup group = new ThreadGroup("threadGroup");
new Thread(group, runnableObject, "YourThreadName", 2000000).start();

С помощью этого примера я увеличил размер стека с 8k (около 260 вызовов) до 2M (достаточно, чтобы не получить StackOverFlowException, конечно, вы можете добавить столько, сколько хотите, пока память может занять это), поэтому, в конце концов, для дальнейших читателей это способ увеличить размер стека,хотя и не рекомендуется, в некоторых случаях это действительно необходимо, например, алгоритм с обширными рекурсивными вызовами и, конечно, выполняя всю тяжелую работу в рабочем потоке(как вы должны) с указанным размером стека и просто "публикуя" изменения в UIs, используя основной поток пользовательского интерфейса с обработчиками или любой механизм, который вы хотели бы использовать для взаимодействия с ним...

надеюсь, что это Помогает...

С уважением!


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

вы должны сделать свой корневой макет относительным макетом и иметь все ваши макеты кадров в качестве детей этого корневой относительный макет.


Если вам нужен этот сложный макет (как многие будут сомневаться), вы все равно можете нарисовать его programticaly в методе onCreate.