C'è qualche condizione in cui finalmente potrebbe non funzionare in java? Grazie.
C'è qualche condizione in cui finalmente potrebbe non funzionare in java? Grazie.
Risposte:
dai Sun Tutorials
Nota: se la JVM viene chiusa durante l'esecuzione del codice try o catch, il blocco finalmente potrebbe non essere eseguito. Allo stesso modo, se il thread che esegue il codice try o catch viene interrotto o ucciso, il blocco finalmente potrebbe non essere eseguito anche se l'applicazione nel suo insieme continua.
Non conosco altri modi in cui il blocco finale non sarebbe stato eseguito ...
System.exit arresta la macchina virtuale.
Termina la Java Virtual Machine attualmente in esecuzione. L'argomento funge da codice di stato; per convenzione, un codice di stato diverso da zero indica una terminazione anomala.
Questo metodo chiama il
exit
metodo in classeRuntime
. Questo metodo non restituisce mai normalmente.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" non viene stampato nel codice sopra.
Solo per espandere ciò che gli altri hanno detto, tutto ciò che non causa qualcosa come l'uscita della JVM incorrerà nel blocco definitivo. Quindi il seguente metodo:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
stranamente compilerà e restituirà 1.
In relazione a System.exit, esistono anche alcuni tipi di errori catastrofici in cui un blocco finalmente potrebbe non essere eseguito. Se la JVM esaurisce completamente la memoria, potrebbe semplicemente uscire senza essere catturata o finalmente accadere.
Nello specifico, ricordo un progetto in cui abbiamo stupidamente cercato di utilizzare
catch (OutOfMemoryError oome) {
// do stuff
}
Questo non ha funzionato perché la JVM non aveva più memoria per eseguire il blocco catch.
try { for (;;); } finally { System.err.println("?"); }
In tal caso, il fine non verrà eseguito (a meno che il deprecato non Thread.stop
venga chiamato, o un equivalente, ad esempio, tramite un'interfaccia di strumenti).
throw
, il finally
blocco verrà eseguito come previsto. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Il tutorial di Sun è stato citato erroneamente qui in questo thread.
Nota: se la JVM viene chiusa durante l'esecuzione del codice try o catch, il blocco finalmente non verrà eseguito. Allo stesso modo, se il thread che esegue il codice try o catch viene interrotto o ucciso, il blocco finalmente non verrà eseguito anche se l'applicazione nel suo insieme continua.
Se guardi attentamente nel tutorial di sun per il blocco finale, non dice "non verrà eseguito" ma "potrebbe non essere eseguito" Ecco la descrizione corretta
Nota: se la JVM viene chiusa durante l'esecuzione del codice try o catch, il blocco finalmente potrebbe non essere eseguito. Allo stesso modo, se il thread che esegue il codice try o catch viene interrotto o ucciso, il blocco finalmente potrebbe non essere eseguito anche se l'applicazione nel suo insieme continua.
L'apparente ragione di questo comportamento è che la chiamata a system.exit () viene elaborata in un thread di sistema runtime che potrebbe richiedere tempo per chiudere la jvm, nel frattempo lo scheduler del thread può chiedere finalmente di eseguire. Quindi finalmente è progettato per essere eseguito sempre, ma se stai chiudendo jvm, può succedere che jvm si spenga prima di essere finalmente eseguito.
Anche se all'interno del try
blocco si verifica un deadlock / livelock .
Ecco il codice che lo dimostra:
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();
}
}
Questo codice produce il seguente output:
t1 inside lock1
t2 inside lock1
e "finalmente" non viene mai stampato
Se la JVM viene chiusa durante l'esecuzione del codice try o catch, il blocco finalmente potrebbe non essere eseguito. ( fonte )
Arresto normale: si verifica quando viene chiuso l'ultimo thread non daemon OPPURE quando Runtime.exit () ( origine )
Quando un thread esce, la JVM esegue un inventario dei thread in esecuzione e se gli unici thread rimasti sono thread daemon, avvia un arresto ordinato. Quando la JVM si arresta, tutti i thread del daemon rimanenti vengono abbandonati e infine i blocchi non vengono eseguiti, gli stack non vengono svolti e la JVM esce. I thread daemon dovrebbero essere usati con parsimonia, poche attività di elaborazione possono essere abbandonate in modo sicuro in qualsiasi momento senza alcuna pulizia. In particolare, è pericoloso utilizzare thread daemon per attività che potrebbero eseguire qualsiasi tipo di I / O. I thread daemon vengono salvati meglio per le attività di "manutenzione", come un thread in background che rimuove periodicamente le voci scadute da una cache in memoria. ( fonte )
L'ultimo thread non daemon esce dall'esempio:
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.");
}
}
Produzione:
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
Nei seguenti casi, infine, il blocco non verrà eseguito: -
System.exit(0)
viene richiamato dal try
blocco. try
blocco Potrebbero esserci anche altri casi marginali, in cui il blocco alla fine non verrà eseguito.
Ci sono due modi per interrompere definitivamente l'esecuzione del codice:
1. Usare System.exit ();
2. Se in qualche modo il controllo dell'esecuzione non raggiunge per provare a bloccare.
Vedere:
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");
}
}
}
}
Mi sono imbattuto in un caso molto specifico del blocco finale non in esecuzione correlato specificamente al framework di gioco.
Sono stato sorpreso di scoprire che il blocco finalmente in questo codice di azione del controller è stato chiamato solo dopo un'eccezione, ma mai quando la chiamata è riuscita effettivamente.
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
Forse il thread viene terminato o qualcosa del genere quando viene chiamato renderBinary (). Sospetto che la stessa cosa accada per altre chiamate render (), ma non l'ho verificato.
Ho risolto il problema spostando renderBinary () dopo il try / catch. Ulteriori indagini hanno rivelato che il gioco fornisce un'annotazione @Finally per creare un metodo che viene eseguito dopo l'esecuzione di un'azione del controller. L'avvertenza qui è che questo verrà chiamato dopo l'esecuzione di QUALSIASI azione nel controller, quindi potrebbe non essere sempre una buona scelta.
//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");
}
}