Programovanie

Výnimky v Jave, časť 2: Pokročilé funkcie a typy

JDK 1.0 predstavil rámec jazykových funkcií a typov knižníc pre prácu s výnimky, čo sú odchýlky od očakávaného správania programu. Prvá polovica tohto tutoriálu obsahovala základné možnosti spracovania výnimiek v Jave. Táto druhá polovica predstavuje pokročilejšie funkcie poskytované JDK 1.0 a jeho nástupcami: JDK 1.4, JDK 7 a JDK 9. Naučte sa, ako predvídať a spravovať výnimky vo vašich programoch Java pomocou pokročilých funkcií, ako sú sledovanie zásobníka, príčiny a reťazenie výnimiek, vyskúšajte -s-prostriedkami, viacnásobný úlovok, konečné opätovné hodenie a chôdza v zásobníku.

Upozorňujeme, že príklady kódov v tomto tutoriále sú kompatibilné s JDK 12.

stiahnuť Získajte kód Stiahnite si zdrojový kód napríklad pre aplikácie v tejto príručke. Vytvoril Jeff Friesen pre JavaWorld.

Spracovanie výnimiek v JDK 1.0 a 1.4: Stopy zásobníka

Každý JVM závit (cesta vykonania) je spojená s a stoh ktorý sa vytvorí, keď sa vytvorí vlákno. Táto dátová štruktúra je rozdelená na rámy, čo sú dátové štruktúry spojené s volaním metód. Z tohto dôvodu sa zásobník každého vlákna často nazýva a zásobník metódového volania.

Pri každom volaní metódy sa vytvorí nový rámec. Každý rámec ukladá lokálne premenné, premenné parametrov (ktoré obsahujú argumenty odovzdané metóde), informácie o návrate k volajúcej metóde, priestor na uloženie návratovej hodnoty, informácie užitočné pri odoslaní výnimky atď.

A trasovanie zásobníka (tiež známy ako a stack backtrace) je správa aktívnych rámcov zásobníka v určitom časovom okamihu počas vykonávania vlákna. Java Hoditeľné trieda (v java.lang balíček) poskytuje metódy na tlač sledovania zásobníka, vyplnenie sledovania zásobníka a prístup k prvkom sledovania zásobníka.

Tlač trasovania zásobníka

Keď hodiť vyhlásenie vrhne, najskôr sa hľadá vhodný chytiť blok vo vykonávacej metóde. Ak sa nenájde, rozvinie sa zásobník volání metód, ktorý hľadá najbližšie chytiť blok, ktorý zvládne výnimku. Ak sa nenájde, JVM sa ukončí vhodnou správou. Zvážte zoznam 1.

Zoznam 1. PrintStackTraceDemo.java (verzia 1)

import java.io.IOException; verejná trieda PrintStackTraceDemo {public static void main (String [] args) hodí IOException {hodiť novú IOException (); }}

Vytvorený príklad zoznamu 1 vytvorí a java.io.IOException objekt a vyhodí tento objekt z hlavný() metóda. Pretože hlavný() nespolupracuje s týmto vyhadzovačom a pretože hlavný() je metóda najvyššej úrovne, JVM sa končí vhodnou správou. V prípade tejto aplikácie sa zobrazí nasledujúca správa:

Výnimka vo vlákne „main“ java.io.IOException na PrintStackTraceDemo.main (PrintStackTraceDemo.java:7)

JVM vydá túto správu volaním Hoditeľnéje void printStackTrace () metóda, ktorá vytlačí trasovanie zásobníka pre vyvolanie Hoditeľné objekt v prúde štandardných chýb. Prvý riadok zobrazuje výsledok vyvolania hodu natiahnuť() metóda. Nasledujúci riadok zobrazuje údaje, ktoré predtým zaznamenal fillInStackTrace () (krátko diskutované).

Ďalšie metódy sledovania zásobníka tlače

Hoditeľnéje preťažený void printStackTrace (PrintStream ps) a void printStackTrace (PrintWriter pw) metódy vygenerujú sledovanie zásobníka do zadaného toku alebo zapisovača.

Stopa zásobníka odhalí zdrojový súbor a číslo riadku, kde bola vytvorená hádzaná položka. V tomto prípade to bolo vytvorené na riadku 7 PrintStackTrace.java zdrojový súbor.

Môžete sa dovolať printStackTrace () priamo, typicky z a chytiť blokovať. Zvážte napríklad druhú verziu súboru PrintStackTraceDemo žiadosť.

Zoznam 2. PrintStackTraceDemo.java (verzia 2)

import java.io.IOException; public class PrintStackTraceDemo {public static void main (String [] args) hodí IOException {try {a (); } catch (IOException ioe) {ioe.printStackTrace (); }} static void a () vyvolá IOException {b (); } static void b () hodí IOException {hodiť novú IOException (); }}

Zoznam 2 odhaľuje a hlavný() metóda, ktorá volá metódu a (), ktorá volá metódu b (). Metóda b () hodí Výnimka IO namietajte proti JVM, ktorý odvíja zásobník metódového volania, kým nenájde hlavný()je chytiť blok, ktorý zvládne výnimku. Výnimka sa rieši vyvolaním printStackTrace () na vrhačke. Táto metóda generuje nasledujúci výstup:

java.io.IOException at PrintStackTraceDemo.b (PrintStackTraceDemo.java:24) at PrintStackTraceDemo.a (PrintStackTraceDemo.java:19) at PrintStackTraceDemo.main (PrintStackTraceDemo.java:9)

printStackTrace () nevypíše názov vlákna. Namiesto toho sa dovoláva natiahnuť() na vrhačke vráti plne kvalifikovaný názov triedy vhadzovačov (java.io.IOException), ktorý sa zobrazuje na prvom riadku. Potom vydá hierarchiu volaní metód: naposledy volanú metódu (b ()) je v hornej časti a hlavný() je dole.

Aký riadok identifikuje stopa zásobníka?

Stopa zásobníka identifikuje riadok, kde je vytvorená hádzaná. Neidentifikuje čiaru, kde je hodená vrhačka (cez hodiť), pokiaľ vrhací priestor nie je hodený na ten istý riadok, kde je vytvorený.

Vyplnenie stopy zásobníka

Hoditeľné vyhlasuje a Hádzateľná fillInStackTrace () metóda, ktorá vyplní trasovanie zásobníka. Vo vyvolaní Hoditeľné objekt, zaznamenáva informácie o aktuálnom stave rámcov zásobníka aktuálneho vlákna. Zvážte zoznam 3.

Zoznam 3. FillInStackTraceDemo.java (verzia 1)

import java.io.IOException; public class FillInStackTraceDemo {public static void main (String [] args) hodí IOException {try {a (); } catch (IOException ioe) {ioe.printStackTrace (); System.out.println (); throw (IOException) ioe.fillInStackTrace (); }} static void a () vyvolá IOException {b (); } static void b () hodí IOException {hodiť novú IOException (); }}

Hlavný rozdiel medzi zoznamom 3 a zoznamom 2 je chytiť bloku throw (IOException) ioe.fillInStackTrace (); vyhlásenie. Toto tvrdenie nahrádza ioestopa zásobníka, po ktorej je vyhodený znovu vyhodený. Mali by ste sledovať tento výstup:

java.io.IOException at FillInStackTraceDemo.b (FillInStackTraceDemo.java:26) at FillInStackTraceDemo.a (FillInStackTraceDemo.java:21) at FillInStackTraceDemo.main (FillInStackTraceDemo.java:9 main) FillInStackTraceDemo.main (FillInStackTraceDemo.java:15)

Namiesto opakovania počiatočného trasovania zásobníka, ktoré identifikuje miesto, kde Výnimka IO objekt bol vytvorený, druhá stopa zásobníka odhaľuje umiestnenie ioe.fillInStackTrace ().

Hádzateľné konštruktory a fillInStackTrace ()

Každý z HoditeľnéKonštruktéri sa dovolávajú fillInStackTrace (). Nasledujúci konštruktor (predstavený v JDK 7) však túto metódu nevyvolá, keď prejdete nepravdivé do writableStackTrace:

Throwable (reťazcová správa, Throwable príčina, boolean enableSuppression, boolean writableStackTrace)

fillInStackTrace () vyvolá natívnu metódu, ktorá prejde zásobníkom aktuálnych vlákien volania metód na vytvorenie sledovania zásobníka. Táto prechádzka je drahá a môže mať vplyv na výkon, ak sa vyskytuje príliš často.

Ak narazíte na situáciu (napríklad s vloženým zariadením), kde je kritický výkon, môžete zabrániť vytvoreniu sledovania zásobníka prepísaním fillInStackTrace (). Pozrite sa na zoznam 4.

Výpis 4. FillInStackTraceDemo.java (verzia 2)

{public static void main (String [] args) hodí NoStackTraceException {try {a (); } catch (NoStackTraceException nste) {nste.printStackTrace (); }} static void a () hodí NoStackTraceException {b (); } static void b () hodí NoStackTraceException {hodiť novú NoStackTraceException (); }} class NoStackTraceException extends Exception {@Override public synchronized Throwable fillInStackTrace () {return this; }}

Zoznam 4 predstavuje NoStackTraceException. Táto vlastná skontrolovaná trieda výnimiek fillInStackTrace () vrátiť sa toto - odkaz na vyvolanie Hoditeľné. Tento program generuje nasledujúci výstup:

NoStackTraceException

Komentujte vyššie uvedené fillInStackTrace () metódy a budete sledovať nasledujúci výstup:

NoStackTraceException at FillInStackTraceDemo.b (FillInStackTraceDemo.java:22) at FillInStackTraceDemo.a (FillInStackTraceDemo.java:17) at FillInStackTraceDemo.main (FillInStackTraceDemo.java:7)

Prístup k prvkom sledovania zásobníka

Občas budete musieť získať prístup k prvkom sledovania zásobníka, aby ste mohli extrahovať podrobnosti potrebné na protokolovanie, identifikáciu zdroja úniku zdrojov a ďalšie účely. The printStackTrace () a fillInStackTrace () metódy túto úlohu nepodporujú, ale bola predstavená JDK 1.4 java.lang.StackTraceElement a jeho metódami na tento účel.

The java.lang.StackTraceElement trieda popisuje prvok predstavujúci rámec zásobníka v sledovaní zásobníka. Jeho metódy možno použiť na vrátenie úplného názvu triedy obsahujúcej bod vykonania predstavovaný týmto prvkom sledovania zásobníka spolu s ďalšími užitočnými informáciami. Tu sú hlavné metódy:

  • Reťazec getClassName () vráti úplný názov triedy obsahujúci bod vykonania predstavovaný týmto stopovým prvkom zásobníka.
  • Reťazec getFileName () vráti názov zdrojového súboru obsahujúceho bod vykonania predstavovaný týmto prvkom sledovania zásobníka.
  • int getLineNumber () vráti číslo riadku zdrojového riadku obsahujúceho bod vykonania predstavovaný týmto prvkom sledovania zásobníka.
  • Reťazec getMethodName () vráti názov metódy obsahujúcej bod vykonania predstavovaný týmto stopovým prvkom zásobníka.
  • boolean isNativeMethod () vracia pravda keď metóda obsahujúca bod vykonania predstavovaný týmto prvkom sledovania zásobníka je natívna metóda.

JDK 1.4 tiež predstavil StackTraceElement [] getStackTrace () metóda do java.lang.Thread a Hoditeľné triedy. Táto metóda vracia pole prvkov sledovania zásobníka predstavujúcich výpis zásobníka vyvolávajúceho vlákna a poskytuje programový prístup k informáciám o sledovaní zásobníka vytlačeným printStackTrace ().

Zoznam 5 ukazuje StackTraceElement a getStackTrace ().

Zoznam 5. StackTraceElementDemo.java (verzia 1)

import java.io.IOException; public class StackTraceElementDemo {public static void main (String [] args) hodí IOException {try {a (); } catch (IOException ioe) {StackTraceElement [] stackTrace = ioe.getStackTrace (); for (int i = 0; i <stackTrace.length; i ++) {System.err.println ("Výnimka vyvolaná z" + stackTrace [i] .getMethodName () + "v triede" + stackTrace [i] .getClassName () + "on line" + stackTrace [i] .getLineNumber () + "súboru" + stackTrace [i] .getFileName ()); System.err.println (); }}} static void a () vyvolá IOException {b (); } static void b () hodí IOException {hodiť novú IOException (); }}

Pri spustení tejto aplikácie uvidíte nasledujúci výstup:

Výnimka vyvolaná z b triedy StackTraceElementDemo na riadok 33 súboru StackTraceElementDemo.java Výnimka vyvolaná z triedy StackTraceElementDemo na riadok 28 súboru StackTraceElementDemo.java Výnimka vyvolaná z hlavnej triedy StackTraceElementDemo na riadok 9 súboru StackTraceE

Nakoniec JDK 1.4 predstavil setStackTrace () metóda do Hoditeľné. Táto metóda je navrhnutá na použitie rámcami vzdialeného volania procedúr (RPC) a inými pokročilými systémami, ktoré klientovi umožňujú prepísať predvolené trasovanie zásobníka, ktoré generuje fillInStackTrace () keď je skonštruovaný vrhač.

Predtým som ukázal, ako prepísať fillInStackTrace () aby sa zabránilo vytváraniu sledovania zásobníka. Namiesto toho môžete nainštalovať nové sledovanie zásobníka pomocou StackTraceElement a setStackTrace (). Vytvorte pole StackTraceElement objekty inicializované pomocou nasledujúceho konštruktora a toto pole odovzdať setStackTrace ():

StackTraceElement (String declaringClass, String methodName, String fileName, int lineNumber)

Zoznam 6 demonštruje StackTraceElement a setStackTrace ().

$config[zx-auto] not found$config[zx-overlay] not found