Wordt een definitief blok altijd uitgevoerd?

Is er een voorwaarde waardoor het uiteindelijk niet in Java kan worden uitgevoerd? Bedankt.


Antwoord 1, autoriteit 100%

uit de Sun Tutorials

Opmerking: als de JVM wordt afgesloten terwijl de try
of catch-code wordt uitgevoerd, dan
het laatste blok wordt mogelijk niet uitgevoerd.
Evenzo, als de thread die de uitvoert
try or catch-code is onderbroken of
gedood, het laatste blok misschien niet
uitvoeren, ook al is de toepassing als
een geheel gaat door.

Ik ken geen andere manieren waarop de definitieve blokkering niet zou worden uitgevoerd…


Antwoord 2, autoriteit 48%

Systeem.exit sluit de virtuele machine af.

Beëindigt de momenteel actieve Java
Virtuele machine. Het argument dient
als statuscode; volgens afspraak, een
niet-nul statuscode geeft abnormaal aan
beëindiging.

Deze methode roept de exitmethode aan in
class Runtime. Deze methode nooit
keert normaal terug.

   try {
        System.out.println("hello");
        System.exit(0);
    }
    finally {
        System.out.println("bye");
    } // try-finally

“tot ziens” wordt niet afgedrukt in bovenstaande code.


Antwoord 3, autoriteit 37%

Om uit te breiden op wat anderen hebben gezegd, alles wat er niet voor zorgt dat zoiets als de JVM wordt afgesloten, wordt uiteindelijk geblokkeerd. Dus de volgende methode:

public static int Stupid() {
  try {
    return 0;
  }
  finally {
    return 1;
  }
}

zal vreemd genoeg zowel compileren als 1 retourneren.


Antwoord 4, autoriteit 10%

In verband met System.exit zijn er ook bepaalde soorten catastrofale fouten waarbij een definitief blok mogelijk niet wordt uitgevoerd. Als de JVM geen geheugen meer heeft, kan hij gewoon afsluiten zonder iets te vangen of uiteindelijk te gebeuren.

In het bijzonder herinner ik me een project waarbij we dwaas probeerden te gebruiken

catch (OutOfMemoryError oome) {
    // do stuff
}

Dit werkte niet omdat de JVM geen geheugen meer had om het catch-blok uit te voeren.


Antwoord 5, autoriteit 7%

try { for (;;); } finally { System.err.println("?"); }

In dat geval wordt de final niet uitgevoerd (tenzij de verouderde Thread.stopwordt aangeroepen, of een equivalent daarvan, bijvoorbeeld via een tools-interface).


Antwoord 6, autoriteit 7%

De Sun-tutorial is hier in deze thread verkeerd geciteerd.

Opmerking: Als de JVM wordt afgesloten terwijl de try-or-catch-code wordt uitgevoerd, wordt het definitieve blok nietuitgevoerd. Evenzo, als de thread die de try-of-catch-code uitvoert, wordt onderbroken of gedood, zal het definitieve blok niet worden uitgevoerd, ook al gaat de toepassing als geheel door.

Als je de sun-tutorial nauwkeurig bekijkt voor eindelijk blokkeren, staat er niet “zal niet uitvoeren” maar “kan niet worden uitgevoerd”
Hier is de juiste beschrijving

Opmerking: als de JVM wordt afgesloten terwijl de try-or-catch-code wordt uitgevoerd, wordt het definitieve blok mogelijkniet uitgevoerd. Evenzo, als de thread die de try-of-catch-code uitvoert, wordt onderbroken of gedood, kan het laatste blok mogelijkniet worden uitgevoerd, ook al gaat de toepassing als geheel door.

De duidelijke reden voor dit gedrag is dat de aanroep van system.exit() wordt verwerkt in een runtime-systeemthread, wat enige tijd kan duren om de jvm af te sluiten, terwijl de thread-planner uiteindelijk kan vragen om het uit te voeren. Dus eindelijk is ontworpen om altijd uit te voeren, maar als je jvm afsluit, kan het gebeuren dat jvm wordt afgesloten voordat het uiteindelijk wordt uitgevoerd.


Antwoord 7, autoriteit 4%

Ook als er een deadlock/livelock optreedt in het try-blok.

Hier is de code die het demonstreert:

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();
    }
}

Deze code produceert de volgende uitvoer:

t1 inside lock1
t2 inside lock1

en “eindelijk” wordt nooit afgedrukt


Antwoord 8, autoriteit 4%

Als de JVM wordt afgesloten terwijl de try-of-catch-code wordt uitgevoerd, wordt het final-blok mogelijk niet uitgevoerd. (bron)

Normaal afsluiten – dit gebeurt ofwel wanneer de laatste niet-daemon-thread wordt afgesloten OF wanneer Runtime.exit() (bron)

Als een thread wordt afgesloten, voert de JVM een inventarisatie uit van actieve threads, en als de enige threads die nog over zijn daemon-threads zijn, initieert het een ordelijke afsluiting. Wanneer de JVM stopt, worden alle resterende daemon-threads verlaten, uiteindelijk worden blokken niet uitgevoerd, worden stapels niet afgewikkeld, de JVM wordt gewoon afgesloten. Daemon-threads moeten spaarzaam worden gebruikt. Weinig verwerkingsactiviteiten kunnen op elk moment veilig worden stopgezet zonder opschoning. In het bijzonder is het gevaarlijk om daemon-threads te gebruiken voor taken die elke vorm van I/O kunnen uitvoeren. Daemon-threads kunnen het beste worden bewaard voor “huishoudelijke” taken, zoals een achtergrondthread die periodiek verlopen items uit een cache in het geheugen verwijdert. (bron)

Laatste niet-daemon-thread verlaat voorbeeld:

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.");
    }
}

Uitvoer:

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

Antwoord 9

In de volgende gevallen wordt de blokkering uiteindelijk niet uitgevoerd:-

  • Als System.exit(0)wordt aangeroepen vanuit het try-blok.
  • Als JVM geen geheugen meer heeft
  • Wanneer uw Java-proces met geweld wordt gedood door taakbeheer of console
  • Deadlock-voorwaarde in uw try-blok
  • Als uw machine uitvalt vanwege een stroomstoring

Er kunnen ook andere randgevallen zijn, waarbij de blokkering uiteindelijk niet wordt uitgevoerd.


Antwoord 10

Er zijn twee manieren om de uitvoering van blokcode definitief te stoppen:
1. Gebruik System.exit();
2. Als de uitvoeringscontrole op de een of andere manier niet reikt om te proberen blok.
Zie:

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");  
        }
    }
  }
}

Antwoord 11

Ik ben een heel specifiek geval tegengekomen van het laatste blok dat niet wordt uitgevoerd, specifiek gerelateerd aan het spelframework.

Ik was verrast toen ik ontdekte dat het laatste blok in deze actiecode van de controller alleen werd aangeroepen na een uitzondering, maar nooit toen de aanroep daadwerkelijk slaagde.

try {
    InputStream is = getInputStreamMethod();
    renderBinary(is, "out.zip");
catch (Exception e) {
    e.printStackTrace();
} finally {
    cleanUp();
}

Misschien wordt de thread beëindigd of zoiets als renderBinary() wordt aangeroepen. Ik vermoed dat hetzelfde gebeurt voor andere render()-aanroepen, maar ik heb het niet geverifieerd.

Ik heb het probleem opgelost door de renderBinary() te verplaatsen naar na de try/catch. Nader onderzoek wees uit dat play een @Final-annotatie biedt om een ​​methode te creëren die wordt uitgevoerd nadat een controlleractie is uitgevoerd. Het voorbehoud hierbij is dat dit wordt aangeroepen na het uitvoeren van ELKE actie in de controller, dus het is misschien niet altijd een goede keuze.


Antwoord 12

//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");   
}
}

Other episodes