JOGL внутри фрейма JavaFX с использованием swingnode [duplicate]

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

sudo yum install php-mysql php-devel php-gd php-pecl-memcache php-pspell php-snmp php-xmlrpc php-xml

355
задан Ziggy 19 June 2015 в 04:55
поделиться

13 ответов

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

В вашем процессе также есть куча, которая живет в в нижней части вашего процесса. Когда вы выделяете память, эта куча может расти в верхнем конце вашего адресного пространства. Как вы можете видеть, существует вероятность того, что куча «столкнется» со стеклом (немного как тектонические пластины !!!).

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

Однако при программировании GUI можно создать непрямую рекурсию. Например, ваше приложение может обрабатывать сообщения с краской, а при их обработке оно может вызывать функцию, которая заставляет систему отправлять другое сообщение с краской. Здесь вы явно не называли себя, но OS / VM сделала это для вас.

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

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

331
ответ дан Keale 15 August 2018 в 16:25
поделиться
  • 1
    Оригинальный плакат: эй, это здорово. Итак, рекурсия всегда отвечает за переполнение стека? Или могут ли другие быть ответственными за них? К сожалению, я использую библиотеку ... но не тот, который я понимаю. – Ziggy 18 October 2008 в 10:04
  • 2
    Ха-ха-ха, так вот вот: while (points & lt; 100) {addMouseListeners (); moveball (); checkforcollision (); пауза (скорость);} Вау, я чувствую себя хромой за то, что не понимаю, что у меня получится стопку слушателей мыши ... Спасибо, ребята! – Ziggy 18 October 2008 в 12:26
  • 3
    Нет, переполнение стека также может происходить из слишком больших переменных, чтобы выделять их в стек, если вы посмотрите статью в Википедии на ru.wikipedia.org/wiki/Stack_overflow . – JB King 5 November 2008 в 00:30
  • 4
    Следует отметить, что почти невозможно "обрабатывать" ошибка переполнения стека. В большинстве сред для обработки ошибки нужно запускать код в стеке, что сложно, если пространства стеков больше нет. – Hot Licks 25 January 2014 в 16:09
  • 5
    @JB King: на самом деле не применяется к Java, где в стек хранятся только примитивные типы и ссылки. Весь большой материал (массивы и объекты) находится в куче. – jcsahnwaldt 23 January 2015 в 03:25

A StackOverflowError - ошибка времени выполнения в java.

Он вызывается, когда количество памяти стека вызовов распределено JVM.

Обычный случай, когда a StackOverflowError выбрасывается, когда стек вызовов превышает из-за чрезмерной глубокой или бесконечной рекурсии.

Пример:

public class Factorial {
    public static int factorial(int n){
        if(n == 1){
            return 1;
        }
        else{
            return n * factorial(n-1);
        }
    }

    public static void main(String[] args){
        System.out.println("Main method started");
        int result = Factorial.factorial(-1);
        System.out.println("Factorial ==>"+result);
        System.out.println("Main method ended");
    }
}

Трассировка стека:

Main method started
Exception in thread "main" java.lang.StackOverflowError
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)

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

5
ответ дан 8bitjunkie 15 August 2018 в 16:25
поделиться

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

Если стек пуст, вы не можете поп, если вы получите стек ошибка переполнения.

Если стек заполнен, вы не можете нажать, если вы получите ошибку переполнения стека.

Таким образом, переполнение стека появляется там, где вы слишком много выделяете стек. Например, в упомянутой рекурсии.

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

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

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

23
ответ дан Cheery 15 August 2018 в 16:25
поделиться
  • 1
    Есть ли такая вещь, как стек underflow ? – Pacerier 29 January 2012 в 16:09
  • 2
    В сборке возможно стекивание стека (выскакивание больше, чем вы нажимаете), хотя на скомпилированных языках это было бы почти невозможно. Я не уверен, вы могли бы найти реализацию C alloca (), которая поддерживает «& quot; отрицательные размеры. – Score_Under 9 February 2013 в 02:14
  • 3
    Переполнение стека означает, что: переполнение стека. Обычно в программе есть один стек, содержащий переменные локальной области - & gt; Нет, каждый поток имеет свой собственный стек, который содержит фреймы стека для каждого вызова метода, который содержит локальные переменные. – Koray Tugay 2 May 2015 в 21:58

Как вы говорите, вам нужно показать код. : -)

Ошибка переполнения стека обычно происходит, когда ваша функция вызывает слишком много гнезд. См. Поток «Переполнение потока стека» для некоторых примеров того, как это происходит (хотя в случае этого вопроса ответы преднамеренно вызывают переполнение стека).

6
ответ дан Community 15 August 2018 в 16:25
поделиться
  • 1
    Я бы полностью хотел добавить код, но поскольку я не знаю, что вызывает переполнение стека, я не уверен, какой код добавить. добавив, что весь код будет хромым, нет? – Ziggy 18 October 2008 в 09:27
  • 2
    Является ли ваш проект открытым исходным кодом? Если это так, просто создайте учетную запись Sourceforge или github и загрузите там весь свой код. :-) – Chris Jester-Young 18 October 2008 в 10:37
  • 3
    это звучит как отличная идея, но я такой noob, что даже не знаю, что мне нужно будет загружать. Например, библиотека, которую я импортирую классы, которые я распространяю и т. Д., Все мне неизвестны. О человек: плохие времена. – Ziggy 18 October 2008 в 10:49

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

8
ответ дан Greg 15 August 2018 в 16:25
поделиться
  • 1
    К сожалению, не видел Java-тег – Greg 18 October 2008 в 09:23
  • 2
    Кроме того, из оригинального плаката здесь: вложенные функции слишком глубоко в чем? Другие функции? И: как распределить память в стек или кучу (поскольку, знаете, я ясно сделал одну из этих вещей, не зная). – Ziggy 18 October 2008 в 09:26
  • 3
    @Ziggy: Да, если одна функция вызывает другую функцию, которая вызывает еще одну функцию и т. Д. После многих уровней, ваша программа будет иметь переполнение стека. [Продолжает] – Chris Jester-Young 18 October 2008 в 10:25
  • 4
    [... продолжение] В Java вы не можете напрямую выделять память из стека (тогда как в C вы можете, и тогда это будет что-то для просмотра), так что это вряд ли станет причиной. В Java все прямые выделения поступают из кучи, используя «новый». – Chris Jester-Young 18 October 2008 в 10:26
  • 5
    @ ChrisJester-Young Не правда ли, что если у меня есть 100 локальных переменных в методе, все из них идут в стек без исключений? – Pacerier 29 January 2012 в 16:08

Чтобы описать это, сначала давайте понять, как хранятся локальные переменные и объекты.

Локальная переменная хранится в стеке: enter image description here [/g1]

Если вы посмотрели на изображении вы должны понимать, как все работает.

Когда вызов функции вызывается Java-приложением, стек стека выделяется в стеке вызовов. Фрейм стека содержит параметры вызываемого метода, его локальные параметры и обратный адрес метода. Адрес возврата обозначает точку выполнения, из которой выполнение программы должно продолжаться после возврата вызванного метода. Если нет места для нового стека кадров, то StackOverflowError вызывается виртуальной машиной Java (JVM).

Наиболее распространенным случаем, который может исчерпать стек Java-приложения, является рекурсия. В рекурсии метод запускается во время его выполнения. Рекурсия рассматривается как мощный метод программирования общего назначения, но ее следует использовать с осторожностью, чтобы избежать StackOverflowError.

Пример, показывающий StackOverflowError, показан ниже:

StackOverflowErrorExample.java:

public class StackOverflowErrorExample {

    public static void recursivePrint(int num) {
        System.out.println("Number: " + num);

        if(num == 0)
            return;
        else
            recursivePrint(++num);
    }

    public static void main(String[] args) {
        StackOverflowErrorExample.recursivePrint(1);
    }
}

В этом примере мы определяем рекурсивный метод, называемый recursivePrint, который печатает целое число, а затем вызывает себя со следующим последовательным целым числом в качестве аргумента. Рекурсия заканчивается, пока мы не перейдем в 0 в качестве параметра. Однако в нашем примере мы передали параметр из 1 и его увеличивающих последователей, следовательно, рекурсия никогда не завершится.

Пример выполнения с использованием флага -Xss1M, который определяет размер стека потоков ниже 1MB, показано ниже:

Number: 1
Number: 2
Number: 3
...
Number: 6262
Number: 6263
Number: 6264
Number: 6265
Number: 6266
Exception in thread "main" java.lang.StackOverflowError
        at java.io.PrintStream.write(PrintStream.java:480)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.write(PrintStream.java:527)
        at java.io.PrintStream.print(PrintStream.java:669)
        at java.io.PrintStream.println(PrintStream.java:806)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:4)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        ...

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

Как работать с StackOverflowError

  1. Простейшим решением является тщательная проверка трассировки стека и обнаружение повторяющегося шаблона номеров строк. Эти номера строк указывают, что код рекурсивно называется. Как только вы обнаружите эти строки, вы должны тщательно проверить свой код и понять, почему рекурсия никогда не заканчивается.
  2. Если вы подтвердили правильность реализации рекурсии, вы можете увеличить размер стека, чтобы разрешить большее количество вызовов. В зависимости от установленной виртуальной машины Java (JVM) размер стека по умолчанию может равняться либо 512 КБ, либо 1 МБ. Вы можете увеличить размер стека потоков, используя флаг -Xss. Этот флаг можно указать либо через конфигурацию проекта, либо через командную строку. Формат аргумента -Xss: -Xss<size>[g|G|m|M|k|K]
74
ответ дан Hearen 15 August 2018 в 16:25
поделиться
  • 1
    Кажется, что ошибка в некоторых версиях java при использовании окон, где аргумент -Xss действует только на новые потоки – goerlibe 8 June 2017 в 09:17

Вот пример

public static void main(String[] args) {
    System.out.println(add5(1));
}

public static int add5(int a) {
    return add5(a) + 5;
}

. StackOverflowError в основном - это когда вы пытаетесь что-то сделать, что, скорее всего, называет себя и продолжает бесконечность (или до тех пор, пока не даст StackOverflowError).

add5(a) будет вызывать себя, а затем снова называть себя и т. д.

0
ответ дан John S. 15 August 2018 в 16:25
поделиться

Если у вас есть такая функция, как:

int foo()
{
    // more stuff
    foo();
}

Затем foo () будет продолжать называть себя, все глубже и глубже, и когда пространство, используемое для отслеживания того, какие функции вы используете, заполненный, вы получаете ошибку переполнения стека.

61
ответ дан Khoth 15 August 2018 в 16:25
поделиться
  • 1
    Неправильно. Ваша функция рекурсивна. Большинство компилируемых языков имеют оптимизацию хвостовой рекурсии. Это означает, что рекурсия сводится к простому циклу, и вы никогда не столкнетесь с переполнением стека с помощью этого фрагмента кода на некоторых системах. – Cheery 18 October 2008 в 10:29
  • 2
    но не в java. – Chii 18 October 2008 в 13:26
  • 3
    Привет, какие нефункциональные языки поддерживают хвостовую рекурсию? – horseyguy 10 August 2009 в 20:52
  • 4
    C, C ++, Python (с незаполненной ласточкой) ... – Clark Gaebel 19 May 2010 в 02:38
  • 5

Часто используется термин «переполнение стека» (переполнение), но неправильное обозначение; атаки не переполняют стек, а буферы в стеке.

- из слайдов слайдов Prof. Доктор Дитер Голманн

0
ответ дан Sergiu 15 August 2018 в 16:25
поделиться

Наиболее распространенной причиной переполнения стека является чрезмерно глубокая или бесконечная рекурсия. Если это ваша проблема, этот учебник о Java Recursion может помочь понять проблему.

4
ответ дан splattne 15 August 2018 в 16:25
поделиться

Вот пример рекурсивного алгоритма для обращения к односвязному списку. На ноутбуке со следующей спецификацией (память 4G, процессор Intel Core i5 2.3GHz, 64-разрядная версия Windows 7) эта функция будет запущена с ошибкой StackOverflow для связанного списка размером около 10 000.

Могу сказать, что мы должны использовать рекурсию разумно, всегда принимая во внимание масштаб системы. Часто рекурсия может быть преобразована в итеративную программу, которая масштабируется лучше. (Одна итеративная версия того же алгоритма приведена в нижней части страницы, она меняет один и тот же список размером 1 миллион за 9 миллисекунд.)

    private static LinkedListNode doReverseRecursively(LinkedListNode x, LinkedListNode first){

    LinkedListNode second = first.next;

    first.next = x;

    if(second != null){
        return doReverseRecursively(first, second);
    }else{
        return first;
    }
}

public static LinkedListNode reverseRecursively(LinkedListNode head){
    return doReverseRecursively(null, head);
}

Итеративная версия того же алгоритма:

    public static LinkedListNode reverseIteratively(LinkedListNode head){
    return doReverseIteratively(null, head);
}   

private static LinkedListNode doReverseIteratively(LinkedListNode x, LinkedListNode first) {

    while (first != null) {
        LinkedListNode second = first.next;
        first.next = x;
        x = first;

        if (second == null) {
            break;
        } else {
            first = second;
        }
    }
    return first;
}


public static LinkedListNode reverseIteratively(LinkedListNode head){
    return doReverseIteratively(null, head);
}
3
ответ дан Yiling 15 August 2018 в 16:25
поделиться
  • 1
    Я думаю, что с JVM, на самом деле не имеет значения, что такое спецификация вашего ноутбука. – kevin 24 October 2013 в 02:48

Это типичный случай java.lang.StackOverflowError ... Метод рекурсивно вызывает себя без выхода в doubleValue(), floatValue() и т. д.

Rational.java

    public class Rational extends Number implements Comparable<Rational> {
        private int num;
        private int denom;

        public Rational(int num, int denom) {
            this.num = num;
            this.denom = denom;
        }

        public int compareTo(Rational r) {
            if ((num / denom) - (r.num / r.denom) > 0) {
                return +1;
            } else if ((num / denom) - (r.num / r.denom) < 0) {
                return -1;
            }
            return 0;
        }

        public Rational add(Rational r) {
            return new Rational(num + r.num, denom + r.denom);
        }

        public Rational sub(Rational r) {
            return new Rational(num - r.num, denom - r.denom);
        }

        public Rational mul(Rational r) {
            return new Rational(num * r.num, denom * r.denom);
        }

        public Rational div(Rational r) {
            return new Rational(num * r.denom, denom * r.num);
        }

        public int gcd(Rational r) {
            int i = 1;
            while (i != 0) {
                i = denom % r.denom;
                denom = r.denom;
                r.denom = i;
            }
            return denom;
        }

        public String toString() {
            String a = num + "/" + denom;
            return a;
        }

        public double doubleValue() {
            return (double) doubleValue();
        }

        public float floatValue() {
            return (float) floatValue();
        }

        public int intValue() {
            return (int) intValue();
        }

        public long longValue() {
            return (long) longValue();
        }
    }

Main.java

    public class Main {

        public static void main(String[] args) {

            Rational a = new Rational(2, 4);
            Rational b = new Rational(2, 6);

            System.out.println(a + " + " + b + " = " + a.add(b));
            System.out.println(a + " - " + b + " = " + a.sub(b));
            System.out.println(a + " * " + b + " = " + a.mul(b));
            System.out.println(a + " / " + b + " = " + a.div(b));

            Rational[] arr = {new Rational(7, 1), new Rational(6, 1),
                    new Rational(5, 1), new Rational(4, 1),
                    new Rational(3, 1), new Rational(2, 1),
                    new Rational(1, 1), new Rational(1, 2),
                    new Rational(1, 3), new Rational(1, 4),
                    new Rational(1, 5), new Rational(1, 6),
                    new Rational(1, 7), new Rational(1, 8),
                    new Rational(1, 9), new Rational(0, 1)};

            selectSort(arr);

            for (int i = 0; i < arr.length - 1; ++i) {
                if (arr[i].compareTo(arr[i + 1]) > 0) {
                    System.exit(1);
                }
            }


            Number n = new Rational(3, 2);

            System.out.println(n.doubleValue());
            System.out.println(n.floatValue());
            System.out.println(n.intValue());
            System.out.println(n.longValue());
        }

        public static <T extends Comparable<? super T>> void selectSort(T[] array) {

            T temp;
            int mini;

            for (int i = 0; i < array.length - 1; ++i) {

                mini = i;

                for (int j = i + 1; j < array.length; ++j) {
                    if (array[j].compareTo(array[mini]) < 0) {
                        mini = j;
                    }
                }

                if (i != mini) {
                    temp = array[i];
                    array[i] = array[mini];
                    array[mini] = temp;
                }
            }
        }
    }

Результат

    2/4 + 2/6 = 4/10
    Exception in thread "main" java.lang.StackOverflowError
    2/4 - 2/6 = 0/-2
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
    2/4 * 2/6 = 4/24
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
    2/4 / 2/6 = 12/8
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)

Вот исходный код StackOverflowError в OpenJDK 7

-1
ответ дан ZhiXingZhe - WangYuQi 15 August 2018 в 16:25
поделиться
5
ответ дан 8bitjunkie 5 September 2018 в 15:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: