É possível construir um trecho de código em Java que tornaria um hipotético java.lang.ChuckNorrisException
inacessível?
Pensamentos que vieram à mente estão usando, por exemplo, interceptadores ou programação orientada a aspectos .
java
exception
exception-handling
aop
Max Charas
fonte
fonte
finalize()
?Respostas:
Eu não tentei isso, então não sei se a JVM restringiria algo assim, mas talvez você possa compilar o código que lança
ChuckNorrisException
, mas em tempo de execução forneça uma definição de classeChuckNorrisException
que não estenda Throwable .ATUALIZAR:
Isso não funciona. Ele gera um erro de verificação:
ATUALIZAÇÃO 2:
Na verdade, você pode fazer isso funcionar se desativar o verificador de código de bytes! (
-Xverify:none
)ATUALIZAÇÃO 3:
Para os que seguem de casa, aqui está o script completo:
Crie as seguintes classes:
Classes de compilação:
Corre:
O comentário "estende RuntimeException" e recompila
ChuckNorrisException.java
apenas :Corre:
Executar sem verificação:
fonte
Object
vez deThrowable
, então? (O compilador não vai permitir isso, mas desde que já tenha desativado o verificador, talvez se poderia cortar o bytecode para fazê-lo.)Depois de refletir sobre isso, criei com sucesso uma exceção incontornável. Eu escolhi nomeá-lo
JulesWinnfield
, no entanto, ao invés de Chuck, porque é uma exceção da mãe que coloca a nuvem em cogumelo. Além disso, pode não ser exatamente o que você tinha em mente, mas certamente não pode ser capturado. Observar:Et voila! Exceção não capturada.
Resultado:
Quando eu tiver um pouco mais de tempo, vou ver se não consigo pensar em outra coisa também.
Além disso, verifique isso:
Causa um estouro de pilha - novamente, as exceções permanecem não detectadas.
fonte
JulesWinfield
? O sistema não será interrompido antes de ser lançado?throw new Whatever()
é realmente duas partes:,Whatever it = new Whatever(); throw it;
e o sistema morre antes de chegar à segunda parte.class cn extends exception{private cn(){}}
Com essa exceção, seria obviamente obrigatório usar a
System.exit(Integer.MIN_VALUE);
partir do construtor, porque é isso que aconteceria se você lançasse uma exceção;)fonte
while(true){}
vez deSystem.exit()
.System.exit()
trabalho instalando um gerenciador de segurança que não o permite. isso transformaria o construtor em uma exceção diferente (SecurityException), que poderia ser detectada.Qualquer código pode pegar Throwable. Portanto, não, qualquer exceção que você criar será uma subclasse de Throwable e estará sujeita a ser capturada.
fonte
hang
própria Throwable tentaria capturar ChuckNorrisException: P(Concedido, tecnicamente , essa exceção nunca é realmente lançada, mas
ChuckNorrisException
não é possível lançar uma adequada - ela lança você primeiro.)fonte
Qualquer exceção que você lançar tem que estender Throwable, para que possa sempre ser capturada. Então a resposta é não.
Se você quiser torná-lo difícil de lidar, você pode substituir métodos
getCause(), getMessage()
,getStackTrace()
,toString()
para jogar outrojava.lang.ChuckNorrisException
.fonte
catch(Throwable t)
apenas armazena em variável para minhas sugestões se aplicam somente no próximo bloco quando o usuário deseja para lidar com a exceçãoMinha resposta é baseada na idéia de @ jtahlborn, mas é um programa Java totalmente funcional , que pode ser empacotado em um arquivo JAR e até implantado no seu servidor de aplicativos favorito como parte de um aplicativo da web .
Antes de tudo, vamos definir a
ChuckNorrisException
classe para não travar a JVM desde o início (Chuck realmente ama travar as JVMs BTW :)Agora vai a
Expendables
classe para construí-lo:E finalmente a
Main
turma para chutar um bumbum:Compile e execute-o com o seguinte comando:
Você obterá a seguinte saída:
Não é surpresa - afinal, é um pontapé redondo :)
fonte
No construtor, você pode iniciar um thread que chama repetidamente
originalThread.stop (ChuckNorisException.this)
O encadeamento poderia capturar a exceção repetidamente, mas continuaria a lançá-la até morrer.
fonte
Não. Todas as exceções em Java devem ser subclasses
java.lang.Throwable
e, embora isso não seja uma boa prática, você pode capturar todos os tipos de exceção da seguinte forma:Consulte a documentação java.lang.Throwable para obter mais informações.
Se você estiver tentando evitar exceções verificadas (aquelas que devem ser tratadas explicitamente), convém subclassificar Error ou RuntimeException.
fonte
Na verdade, a resposta aceita não é tão boa porque o Java precisa ser executado sem verificação, ou seja, o código não funcionaria em circunstâncias normais.
AspectJ para o resgate da solução real !
Classe de exceção:
Aspecto:
Aplicação de exemplo:
Resultado:
fonte
Uma variante do tema é o fato surpreendente de que você pode lançar exceções verificadas não declaradas do código Java. Como não está declarado na assinatura dos métodos, o compilador não permitirá que você capture a exceção em si, mas pode capturá-la como java.lang.Exception.
Aqui está uma classe auxiliar que permite lançar qualquer coisa, declarada ou não:
Agora
throw SneakyThrow.sneak(new ChuckNorrisException());
lança um ChuckNorrisException, mas o compilador reclamasobre como capturar uma exceção que não é lançada se ChuckNorrisException for uma exceção verificada.
fonte
Os únicos
ChuckNorrisException
s em Java devem serOutOfMemoryError
eStackOverflowError
.Você pode realmente "capturá-los" da maneira que um
catch(OutOfMemoryError ex)
será executado caso a exceção seja lançada, mas esse bloco retrocederá automaticamente a exceção para o chamador.Eu não acho que
public class ChuckNorrisError extends Error
isso funcione, mas você pode tentar. Não encontrei nenhuma documentação sobre a extensãoError
fonte
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Sim, e aqui está a resposta: Crie o seu de
java.lang.ChuckNorrisException
forma que não seja uma instância dojava.lang.Throwable
. Por quê? Um objeto que não pode ser jogado é inacessível por definição, porque você nunca pode capturar algo que nunca pode ser lançado.fonte
java.lang.ChuckNorrisException
devem ser uma exceção, muito menos jogáveis #Você pode manter ChuckNorris interno ou privado e encapsulá-lo ou segui-lo ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
fonte
Dois problemas fundamentais com o tratamento de exceções em Java são que ele usa o tipo de exceção para indicar se uma ação deve ser executada com base nela e que qualquer coisa que execute uma ação com base em uma exceção (por exemplo, "pega") é considerada como resolvida a condição subjacente. Seria útil ter um meio pelo qual um objeto de exceção pudesse decidir quais manipuladores devem ser executados e se os manipuladores que executaram até agora limparam as coisas o suficiente para que o presente método satisfaça suas condições de saída. Embora isso possa ser usado para tornar exceções "inatacáveis", dois usos maiores seriam (1) criar exceções que só serão consideradas manipuladas quando forem capturadas pelo código que realmente sabe lidar com elas,
finally
FooException
durante umfinally
bloco durante o desenrolamento de aBarException
, ambas as exceções devem propagar a pilha de chamadas; ambos devem ser capturáveis, mas o desenrolamento deve continuar até que ambos sejam capturados). Infelizmente, acho que não haveria maneira de fazer com que o código de tratamento de exceções existente funcionasse dessa maneira sem interromper as coisas.fonte
finally
bloco está limpando de uma exceção anterior, é bem possível que uma exceção, na ausência da outra, possa ser algo com o qual se espera que o código manipule e continue, mas lidar com um e ignorar o outro seria ruim. Porém, não há mecanismo para produzir uma exceção composta que ambos os manipuladores processariam.Foo
podem distinguir entre uma exceção queFoo
se lançou ou deliberadamente quer fingir que se lançou, de uma queFoo
não esperava que acontecesse quando foi chamando algum outro método. É sobre isso que a noção de exceções "verificadas" deve ser "sobre".É facilmente possível simular uma exceção não capturada no encadeamento atual. Isso acionará o comportamento regular de uma exceção não capturada e, portanto, executará o trabalho semanticamente. No entanto, não necessariamente interromperá a execução do encadeamento atual, pois nenhuma exceção é realmente lançada.
Isso é realmente útil em situações (muito raras), por exemplo, quando o
Error
manuseio adequado é necessário, mas o método é chamado a partir de uma estrutura que captura (e descarta) qualquerThrowable
.fonte
Chame System.exit (1) em
finalize
, e basta lançar uma cópia da exceção de todos os outros métodos, para que o programa saia.fonte