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 ioe
stopa 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 ()
vraciapravda
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 ()
.