В чём разница между StackOverFlowError и OutOfMemoryError?
StackOverFlowError и OutOfMemoryError выбрасываются при недостатке памяти у jvm, но в чём их разница?
Ответы (1 шт):
StackOverFlowError
Эта ошибка происходит, когда переполнен стек (по-английски - stack). Если кратко, то
в стеке хранятся только ссылки на объекты, которые находятся в куче. Ещё в стеке хранятся примитивы и список методов, "кто кого вызвал". Вообщем StackOverFlowError происходит при зацикливании вызова методов. Например:
public static void doSomething(){
doSomething();
}
При вызове метода doSomething() произойдёт StackOverFlowError, так как стек будет переполнен.
Чтобы исправить StackOverFlowError нужно найти такое зацикливание и убрать его. На самом деле, вызов метода из самого себя использовать можно, но делать это стоит осторожно. Это будет называться рекурсия. Вот пример использования рекурсии для вычисления факториала:
public static int factorial(int number){
if(number < 0){
throw new IllegalArgumentException("Число меньше 0");
}
if(number == 0 || number == 1){
return 1;
}
return factorial(number - 1) * number;
}
В таком случае StackOverFlowError не произойдёт, так как из метода в конце-концов будет выполнен выход.
В рекурсивных методах следует также проверять, что число, пришедшее в параметрах, не слишком большое. В противном случае может оказаться, что метод будет вызывать сам себя хоть и не бесконечное, но всё же достаточное количество раз, чтобы произошла ошибка StackOverFlowError.
OutOfMemoryError
Это ошибка происходит, когда переполнена куча (по-английски - heap). Если кратко, то в куче хранятся объекты. Именно объекты, а не ссылки на них. То есть OutOfMemoryError произойдёт тогда, когда в куче кончится место создавать объекты. Вот пример:
public class Test{
public static void main(String [] args){
Object[][] toManyObjects = new Object[1000000][1000000];
}
}
Этот код бует скомпилирован, но при запуске произойдёт OutOfMemoryError:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Test.main(Test.java:5)
Ведь в массиве гигантское количество объектов, и в куче нет столько места.
Конечно, никто не будет делать такие глупые ошибки. Обычно OutOfMemoryError происходит тоже при зацикливании, но не при бесконечном вызове метода, а в обычных циклах (for, while, do-while), если из таких циклов нет выхода, а в теле цикла создаются какие-либо объекты.
Примеров кодов с OutOfMemoryError масса в интернете: можете посмотреть вопросы на StackOverFlow на русском, в которых упоминается OutOfMemoryError, если вам интересно посмотреть в каких случаях такая ошибка может произойти.
Подведу итоги
OutOfMemoryErrorпроисходит при переполнении кучи, аStackOverFlowError- при переполнении стека;StackOverFlowErrorпроисходит при бесконечном вызове метода, аOutOfMemoryError- при зацикливании создания объектов;- И того, и другое нужно исправить: найти зацикливание и устранить его.
Ссылки
Статья на хабре про память в java