Gyakorlati alapok

Kivételesen beszéljünk a kivételkezelésről

 

Bevezetés

 

Bevezetés

Kapcsolódó fejezetek

 

Bevezetés

 

A programok rengetegféle funkciót teljesíthetnek, ezért futásuk számtalan ok miatt szakadhat meg, például:

A fenti példákból jól láthatjuk, hogy kétféle futási probléma merülhet fel:

  1. amelyik nem rajtunk múlik, például áramkimaradás, távoli szerver, erőforrás összeomlása,

  2. amelyik kizárólag rajtunk múlik, ezért adott körülmények között kísérletet tehetünk lekezelésére, megszüntetésére. Ezek tipikusan a programozási hibák. Sőt néha az is lehetséges, hogy ezeket nem is maga a Java-alkalmazás programozója, hanem egy programozási szinttel lejjebb előzetesen a JVM rendszerprogramozója követi el. Programozótól függetlenül ezen hibákra aztán hackerek vadásznak, hogy a felfedezett exploitokat (biztonsági réseket) valamilyen módon pénzzé tegyék. De természetesen az alkalmazás-szintű hibát magának a programozónak kell lekezelnie.

A Java-alkalmazás futásának megszakadása esetén 2 végrehajtási irány lehetséges:

  1. meg kell kísérelni visszahozni a programot egy újfent futtatható állapotba,

  2. ha ez nem lehetséges, olyan korrekt állapotba kell terelni, hogy a program viszonylag "normálisan" álljon le.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

A fentiekből nyilvánvalóan következik, hogy a programozónak előre kell látnia azon hibalehetőségeket, amelyek csakis rajta vagy a futási körülményeken múlnak és elhárításukra határozott, jól megvalósítható programozási lépéseket kell tennie. A Java nyelv ezt natívan képes támogatni.

 

A Java-nyelv a programfutási hibát kivételnek (exception) nevezi. Lekezelése előre beépítetten, osztályszinten történik (java.lang.Throwable), amely által egységes, a különböző hibatípusokat is jól detektáló feldolgozást képes biztosítani.

 

Programfutási hiba során a JVM olyan művelettel vagy problémával szembesül, amelyet nem tud végrehajtani. Ezt érzékelve a JVM létrehoz egy kivételkezelő objektumot, amelyik fontos információkat tartalmaz a hiba fajtájáról és a program aktuális állapotairól. A pillanatnyilag kialakult programozási helyzetet úgy is nevezhetjük, hogy a hibás metódus dobott egy kivételt (throw an exception), más szavakkal: kiváltott egy kivételt.

 

Az alábbi Java-kódban nem túl elegáns módon elkövetjük a "klasszikus" programozási hibát: 0-val osztunk. Nagy valószínűséggel a hibát így direktben senki sem fogja elkövetni, de minél bonyolultabb egy program, benne minél több változó értéke változik folyamatosan (sőt minél több párhuzamos programszálon fut), annál nagyobb a valószínűsége az ehhez hasonló kivételeknek. A program futása hibaüzenettel megszakad, de a hibadetektálás magas szintű, hiszen a JVM képes volt megállapítani a hiba jellegét és főbb tulajdonságait:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
    public static void main(String[] args) {
    System.out.println(4 / 0);
    }
}

 

Végeredmény (hibaüzenet):

Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:152)

 

A magas szintű hibadetektálás ellenére a program futása mégis megszakad; a hiba utáni rész már nem fut le:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
    public static void main(String[] args) {
    System.out.println(4 / 0);

    System.out.println("Ez már nem fog lefutni.");
    }
}

 

Végeredmény (hibaüzenet):

Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:152)

 

Alapvető programozási követelmény tehát olyan kód megalkotása, amely megbízható és "figyelmes" módon képes még időben "elkapni" a lehetséges hibákat, kivételeket (catching an exception). Ám ezen követelményen túllépve maga a Java is tovább szigorítja a kivételek lekezelését: definiál ellenőrzött és nem ellenőrzött kivételeket.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

Az ellenőrzött kivételeket egyenesen kötelező lekezelni, másként fordítási hibát kapunk.

 

Ilyen jellegű kóddal már találkozhattunk például a Lottózzunk, avagy töltsük ki a telitalálatos szelvényt! című fejezetben. Ott a programszál futásának késleltetését kötelező volt a kivételkezelés szabványos try-catch blokkjába tennünk, másként hibaüzenetet kaptunk (az már más kérdés, hogy a catch blokkot nem kezeltük le):

 

try{
    Thread.sleep(200);
    }catch(InterruptedException ie){}
}
 

Az ellenőrzött kivételek bevezetésével jóval megbízhatóbb kód állítható elő, hiszen a programozó a kötelező hibafigyelés és kezelés miatt egyszerűen rá van kényszerítve biztonságos kód megalkotására.

 

Ám az is nyilvánvaló, hogy mindennek bizony vannak ésszerűségi határai. Ugyanis elméletileg minden művelethez hozzárendelhetünk valamilyen szintű kivétel-, hibakezelést (azaz megkíséreljük a program minden egyes műveletét programozói ellenőrzés alá vonni), amelynek következménye azonban átláthatatlanul megnövekedett kódtömeg és veszélyes mértékű túlbonyolítás lehet.

 

A kompromisszumos megoldás tehát -amit a Java nyelv megalkotói már megtettek-, a legfontosabb, a "legveszélyesebb", mondhatni tipikus kivételek típusos definiálása és szabványos, osztályszintű hierarchiába rendezett publikálása azon okból, hogy a felhasználó programozó a minél biztonságosabban futó kód érdekében "elkaphassa" azokat.

 

Kapcsolódó fejezetek