Existe alguma condição em que finalmente não pode ser executado em java? Obrigado.
Existe alguma condição em que finalmente não pode ser executado em java? Obrigado.
Respostas:
Nota: Se a JVM sair enquanto o código try ou catch está sendo executado, o bloco finally pode não ser executado. Da mesma forma, se o encadeamento que executa o código try ou catch for interrompido ou eliminado, o bloco finally pode não ser executado mesmo que o aplicativo como um todo continue.
Não conheço nenhuma outra maneira de o bloco finally não ser executado ...
System.exit desliga a máquina virtual.
Encerra a Java Virtual Machine atualmente em execução. O argumento serve como um código de status; por convenção, um código de status diferente de zero indica encerramento anormal.
Este método chama o
exit
método em classeRuntime
. Este método nunca retorna normalmente.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" não é impresso no código acima.
Apenas para expandir o que os outros disseram, qualquer coisa que não cause algo como a saída da JVM incorrerá no bloqueio finally. Portanto, o seguinte método:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
irá estranhamente compilar e retornar 1.
Relacionado a System.exit, também existem certos tipos de falha catastrófica em que um bloco final pode não ser executado. Se a JVM ficar totalmente sem memória, ela pode simplesmente sair sem travar ou finalmente acontecer.
Especificamente, lembro-me de um projeto em que tentamos tolamente usar
catch (OutOfMemoryError oome) {
// do stuff
}
Isso não funcionou porque a JVM não tinha mais memória para executar o bloco catch.
try { for (;;); } finally { System.err.println("?"); }
Nesse caso, o finally não será executado (a menos que o obsoleto Thread.stop
seja chamado, ou um equivalente, digamos, por meio de uma interface de ferramentas).
throw
, o finally
bloco será executado conforme o esperado. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
O tutorial do Sun foi citado erroneamente aqui neste tópico.
Nota: Se a JVM sair enquanto o código try ou catch estiver sendo executado, o bloco finally não será executado. Da mesma forma, se o thread que executa o código try ou catch for interrompido ou eliminado, o bloco finally irá não executado, embora o aplicativo como um todo continue.
Se você olhar atentamente para o tutorial do sol para o bloco final, ele não diz "não será executado", mas "pode não ser executado" Aqui está a descrição correta
Nota: Se a JVM sair enquanto o código try ou catch está sendo executado, o bloco finally pode não ser executado. Da mesma forma, se o encadeamento que executa o código try ou catch for interrompido ou eliminado, o bloco finally pode não ser executado mesmo que o aplicativo como um todo continue.
A razão aparente para esse comportamento é que a chamada para system.exit () é processada em um thread do sistema em tempo de execução que pode demorar para desligar o jvm, enquanto o planejador de thread pode finalmente pedir para ser executado. Então, finalmente, é projetado para executar sempre, mas se você estiver encerrando o jvm, pode acontecer que o jvm seja encerrado antes de finalmente ser executado.
Além disso, se um deadlock / livelock acontecer dentro try
bloco.
Aqui está o código que demonstra isso:
public class DeadLocker {
private static class SampleRunnable implements Runnable {
private String threadId;
private Object lock1;
private Object lock2;
public SampleRunnable(String threadId, Object lock1, Object lock2) {
super();
this.threadId = threadId;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
try {
synchronized (lock1) {
System.out.println(threadId + " inside lock1");
Thread.sleep(1000);
synchronized (lock2) {
System.out.println(threadId + " inside lock2");
}
}
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
}
public static void main(String[] args) throws Exception {
Object ob1 = new Object();
Object ob2 = new Object();
Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
t1.start();
t2.start();
}
}
Este código produz a seguinte saída:
t1 inside lock1
t2 inside lock1
e "finalmente" nunca é impresso
Se a JVM sair enquanto o código try ou catch estiver sendo executado, o bloco finally pode não ser executado. ( fonte )
Desligamento normal - isso ocorre quando o último segmento não-daemon sai OU quando Runtime.exit () ( fonte )
Quando um encadeamento é encerrado, a JVM executa um inventário de encadeamentos em execução e, se os únicos encadeamentos restantes forem encadeamentos daemon, ele inicia um encerramento ordenado. Quando a JVM é interrompida, quaisquer encadeamentos de daemon restantes são abandonados, finalmente os blocos não são executados, as pilhas não são desenroladas, a JVM apenas sai. Os encadeamentos daemon devem ser usados com moderação; poucas atividades de processamento podem ser abandonadas com segurança a qualquer momento, sem limpeza. Em particular, é perigoso usar threads de daemon para tarefas que podem realizar qualquer tipo de E / S. Os encadeamentos daemon são melhor salvos para tarefas de "manutenção", como um encadeamento em segundo plano que remove entradas expiradas periodicamente de um cache na memória. ( fonte )
Exemplo de últimas saídas de thread não daemon:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("Is alive");
Thread.sleep(10);
// throw new RuntimeException();
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.out.println("This will never be executed.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
daemon.start();
Thread.sleep(100);
// daemon.stop();
System.out.println("Last non-daemon thread exits.");
}
}
Resultado:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
Nos seguintes casos, o bloco final não será executado: -
System.exit(0)
é invocado do try
bloco. try
bloco Também pode haver outros casos marginais, onde o bloco final não será executado.
Existem duas maneiras de parar finalmente a execução do código:
1. Use System.exit ();
2. Se de alguma forma, o controle de execução não chega a tentar bloquear.
Vejo:
public class Main
{
public static void main (String[]args)
{
if(true){
System.out.println("will exceute");
}else{
try{
System.out.println("result = "+5/0);
}catch(ArithmeticException e){
System.out.println("will not exceute");
}finally{
System.out.println("will not exceute");
}
}
}
}
Eu me deparei com um caso muito específico do bloco finally não executando, relacionado especificamente à estrutura de reprodução.
Fiquei surpreso ao descobrir que o bloco finally neste código de ação do controlador só foi chamado depois de uma exceção, mas nunca quando a chamada realmente foi bem-sucedida.
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
Talvez o thread seja encerrado ou algo assim quando renderBinary () é chamado. Eu suspeitaria que a mesma coisa acontece com outras chamadas render (), mas não verifiquei isso.
Resolvi o problema movendo renderBinary () para depois de try / catch. Uma investigação mais aprofundada revelou que play fornece uma anotação @Finally para criar um método que é executado após a execução de uma ação do controlador. A ressalva aqui é que ele será chamado após a execução de QUALQUER ação no controlador, portanto, nem sempre é uma boa escolha.
//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[s.length];
z[10] = 1000;
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
finally
{
System.out.println("Inner finally");
}
}
catch(ArithmeticException e)
{
System.out.println(e);
}
finally
{
System.out.println("Outer Finally");
}
System.out.println("Remaining Code");
}
}