Eu costumava pensar que não, mas ontem eu tive que fazer isso. É um aplicativo que usa Akka (uma implementação de sistema de ator para a JVM) para processar tarefas assíncronas. Um dos atores realiza alguma manipulação de PDF e, como a biblioteca é de buggy, ela morre com um de StackOverflowError
vez em quando.
O segundo aspecto é que o Akka está configurado para encerrar todo o sistema de atores se algum erro fatal da JVM (por exemplo, StackOverflowError) for detectado.
O terceiro aspecto é que esse sistema ator é incorporado a um aplicativo da Web (por motivos legados, WTF); portanto, quando o sistema do ator é desligado, o aplicativo da Web não é. O efeito líquido é que, em StackOverflowError
nosso aplicativo de processamento de tarefas, torna-se apenas um aplicativo Web vazio.
Como uma solução rápida, eu tive que capturar o StackOverflowError
ser jogado, para que o pool de threads do sistema de atores não fosse destruído. Isso me levou a pensar que talvez às vezes seja bom capturar esses erros, especialmente em contextos como este? Quando há um pool de threads processando tarefas arbitrárias? Ao contrário de um OutOfMemoryError
, não consigo imaginar como um StackOverflowError
aplicativo pode deixar um estado inconsistente. A pilha é limpa após esse erro, para que o cálculo possa continuar normalmente. Mas talvez esteja perdendo algo importante.
Além disso, note que sou a favor de corrigir o erro em primeiro lugar (na verdade, eu já corrigi um SOE nesse mesmo aplicativo há alguns dias), mas eu realmente não sei quando isso tipo de situação pode surgir.
Por que seria melhor reiniciar o processo da JVM em vez de capturar a StackOverflowError
marca, marcar a tarefa como falhada e continuar com meus negócios?
Existe alguma razão convincente para nunca pegar empresas estatais? Exceto "melhores práticas", que é um termo vago que não me diz nada.
fonte
StackOverflowException
s geralmente são devidos a uma cadeia não terminável de chamadas de método - aumentar o espaço da pilha aumentaria o custo da memória de um novo thread sem nenhum benefício.:-)
Respostas:
Como regra geral, se nunca fosse absolutamente aceitável fazer alguma coisa, e houvesse acordo sobre isso, os implementadores de linguagem não teriam permitido. Quase não existem máximas tão unanimemente claras. (Felizmente, porque é isso que nos mantém programadores humanos em empregos!)
Parece que você encontrou uma situação em que a captura desse erro é a melhor opção para você: permite que seu aplicativo funcione, enquanto todas as outras alternativas não, e é isso que conta no final. Todas as "melhores práticas" são simplesmente resumos de longas experiências com muitos casos que geralmente podem ser usados no lugar de uma análise detalhada de um caso específico para economizar tempo; no seu caso, você já fez a análise específica e obteve um resultado diferente. Parabéns, você é capaz de pensar de forma independente!
(Dito isso, certamente há situações em que um estouro de pilha pode deixar um aplicativo inconsistente como uma exaustão de memória. Imagine que algum objeto seja construído e inicializado com a ajuda de chamadas de método internas aninhadas - se um deles jogar, o objeto pode muito bem estar em um estado que não deveria ser possível, como se uma alocação tivesse falhado. Mas isso não significa que sua solução ainda não possa ser a melhor.
fonte
StackOverflowException
uma exceção não capturável. Eu sei, é uma plataforma diferente, mas achei que eles poderiam ter um motivo. Além disso, seu argumento em relação à inicialização do objeto é direto. Isso me leva a pensar que eu deveria pegar esse SOE algumas camadas de abstração abaixo, para não pegar o SOE "errado".situations here
deveria sersituations where
.Não sei se existem riscos específicos da JVM aqui, mas no geral parece bastante sensato.
Por exemplo, existem algoritmos recursivos, como quicksort ingênuo, que possuem
log(n)
profundidade de pilha em um caso típico, mas, na pior das hipóteses, eles se degradam em profundidaden
que podem explodir a pilha.O pior caso é raro e improvável que aconteça novamente se você reiniciar a classificação no conjunto parcialmente classificado, portanto, faz muito sentido capturar a exceção de estouro de pilha quando isso acontece e reiniciar o trabalho em vez de tentar impedir que erros ocorram ou matem aplicação inteira.
fonte