O que pode causar um java.lang.StackOverflowError
? A impressão da pilha que obtenho não é muito profunda (apenas 5 métodos).
java
callstack
stack-overflow
Ivan
fonte
fonte
Respostas:
Verifique se há chamadas recusivas para métodos. Principalmente, é causado quando há uma chamada recursiva para um método. Um exemplo simples é
public static void main(String... args) { Main main = new Main(); main.testMethod(1); } public void testMethod(int i) { testMethod(i); System.out.println(i); }
Aqui, o System.out.println (i); será repetidamente empurrado para a pilha quando o testMethod for chamado.
fonte
Um dos argumentos (opcionais) para a JVM é o tamanho da pilha. É -Xss. Não sei qual é o valor padrão, mas se a quantidade total de coisas na pilha exceder esse valor, você obterá esse erro.
Geralmente, recursão infinita é a causa disso, mas se você estivesse vendo isso, o rastreamento de pilha teria mais de 5 quadros.
Tente adicionar um argumento -Xss (ou aumentar o valor de um) para ver se isso desaparece.
fonte
O que realmente causa um java.lang.StackOverflowError é normalmente a recursão não intencional. Para mim, é frequentemente quando pretendo chamar um super método para o método substituído. Como neste caso:
public class Vehicle { public void accelerate(float acceleration, float maxVelocity) { // set the acceleration } } public class SpaceShip extends Vehicle { @Override public void accelerate(float acceleration, float maxVelocity) { // update the flux capacitor and call super.accelerate // oops meant to call super.accelerate(acceleration, maxVelocity); // but accidentally wrote this instead. A StackOverflow is in our future. this.accelerate(acceleration, maxVelocity); } }
Primeiro, é útil saber o que acontece nos bastidores quando chamamos uma função. Os argumentos e o endereço de onde o método foi chamado são colocados na pilha (consulte http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ) para que o método chamado possa acessar os argumentos e para que quando o método chamado for concluído, a execução pode continuar após a chamada. Mas como estamos chamando this.accelerate (acceleration, maxVelocity) recursivamente (a recursão ocorre vagamente quando um método chama a si mesmo. Para obter mais informações, consulte http://en.wikipedia.org/wiki/Recursion_(computer_science)) estamos em uma situação conhecida como recursão infinita e continuamos empilhando os argumentos e o endereço de retorno na pilha de chamadas. Como a pilha de chamadas tem tamanho finito, eventualmente ficamos sem espaço. A falta de espaço na pilha de chamadas é conhecida como estouro. Isso ocorre porque estamos tentando usar mais espaço de pilha do que temos e os dados literalmente estouram a pilha. Na linguagem de programação Java, isso resulta na exceção de tempo de execução java.lang.StackOverflow e interromperá imediatamente o programa.
O exemplo acima é um tanto simplificado (embora isso aconteça comigo mais do que eu gostaria de admitir). A mesma coisa pode acontecer de uma maneira mais geral, tornando-o um pouco mais difícil de rastrear. No entanto, em geral, o StackOverflow é geralmente muito fácil de resolver, uma vez que ocorre.
Em teoria, também é possível ter um estouro de pilha sem recursão, mas na prática, parece ser um evento bastante raro.
fonte
O que é
java.lang.StackOverflowError
O erro
java.lang.StackOverflowError
é lançado para indicar que a pilha do aplicativo foi esgotada, devido à recursão profunda, ou seja, seu programa / script recorre muito profundamente.Detalhes
A classe
StackOverflowError
extendsVirtualMachineError
que indica que a JVM está ou ficou sem recursos e não pode operar mais. OVirtualMachineError
que estende aError
classe é usado para indicar os problemas sérios que um aplicativo não deve detectar. Um método não pode declarar esses erros em suathrow
cláusula porque esses erros são condições anormais que nunca foram esperadas.Um exemplo
Minimal, Complete, and Verifiable Example
:package demo; public class StackOverflowErrorExample { public static void main(String[] args) { StackOverflowErrorExample.recursivePrint(1); } public static void recursivePrint(int num) { System.out.println("Number: " + num); if(num == 0) return; else recursivePrint(++num); } }
Saída do console
Number: 1 Number: 2 . . . Number: 8645 Number: 8646 Number: 8647Exception in thread "main" java.lang.StackOverflowError at java.io.FileOutputStream.write(Unknown Source) at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at java.io.BufferedOutputStream.flush(Unknown Source) at java.io.PrintStream.write(Unknown Source) at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source) at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source) at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source) at java.io.OutputStreamWriter.flushBuffer(Unknown Source) at java.io.PrintStream.newLine(Unknown Source) at java.io.PrintStream.println(Unknown Source) at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11) at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16) . . . at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
Explicação
Quando uma chamada de função é invocada por um aplicativo Java, um frame de pilha é alocado na pilha de chamadas . O
stack frame
contém os parâmetros do método invocado, seus parâmetros locais e o endereço de retorno do método. O endereço de retorno denota o ponto de execução a partir do qual a execução do programa deve continuar após o retorno do método invocado. Se não houver espaço para um novo quadro de pilha, oStackOverflowError
será lançado pela Java Virtual Machine (JVM).O caso mais comum que pode esgotar a pilha de um aplicativo Java é a recursão. Na recursão, um método invoca a si mesmo durante sua execução.
Recursion
uma das mais poderosas técnicas de programação de uso geral, mas deve ser usada com cautela, paraStackOverflowError
que seja evitada.Referências
fonte
Quando uma chamada de função é invocada por um aplicativo Java, um quadro de pilha é alocado na pilha de chamadas. O quadro de pilha contém os parâmetros do método invocado, seus parâmetros locais e o endereço de retorno do método.
O endereço de retorno denota o ponto de execução a partir do qual a execução do programa deve continuar após o retorno do método invocado. Se não houver espaço para um novo quadro de pilha, o StackOverflowError será lançado pela Java Virtual Machine (JVM) .
O caso mais comum que pode esgotar a pilha de um aplicativo Java é a recursão.
Por favor, dê uma olhada
Como resolver StackOverflowError
fonte
Solução para usuários do Hibernate ao analisar dados:
Eu tive esse erro porque estava analisando uma lista de objetos mapeados em ambos os lados
@OneToMany
e@ManyToOne
para json usando jackson, o que causou um loop infinito.Se você estiver na mesma situação, pode resolver isso usando
@JsonManagedReference
e as@JsonBackReference
anotações.Definições da API:
JsonManagedReference ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html ):
JsonBackReference: ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html ):
Exemplo:
Owner.java:
@JsonManagedReference @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER) Set<Car> cars;
Car.java:
@JsonBackReference @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "owner_id") private Owner owner;
Outra solução é usar
@JsonIgnore
que apenas definirá nulo para o campo.fonte
Criei um programa com hibernate, no qual criei duas classes POJO, ambas com um objeto uma da outra como membros de dados. Quando no método principal tentei salvá-los no banco de dados também obtive este erro.
Isso acontece porque as duas classes estão se referindo uma à outra, criando, portanto, um loop que causa esse erro.
Portanto, verifique se esse tipo de relacionamento existe em seu programa.
fonte
As exceções de estouro de pilha podem ocorrer quando uma pilha de encadeamentos continua a crescer em tamanho até atingir o limite máximo.
Ajustando as opções de tamanhos de pilha (Xss e Xmso) ...
Eu sugiro que você veja este link: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Existem muitas causas possíveis para um StackOverflowError, como você pode ver no link ....
fonte
No meu caso, tenho duas atividades. Na segunda atividade esqueci de colocar super no método onCreate.
super.onCreate(savedInstanceState);
fonte
StackOverflowError
, não creio que esteja respondendo à pergunta. Acho que uma resposta adequada deve listar outras maneiras de obter essa exceção, além de usar muita recursão, ou dizer que definitivamente não há outra maneira de obter essa exceção, exceto lançá-la manualmente.