Programiranje

Izjeme v Javi, 2. del: Napredne funkcije in vrste

JDK 1.0 je predstavil okvir jezikovnih funkcij in tipov knjižnic za obravnavo izjeme, ki se razlikujejo od pričakovanega vedenja programa. Prva polovica te vadnice je zajemala osnovne zmožnosti Java za obdelavo izjem. Ta druga polovica predstavlja naprednejše funkcije, ki jih nudi JDK 1.0 in njegovi nasledniki: JDK 1.4, JDK 7 in JDK 9. Naučite se predvideti in upravljati izjeme v svojih programih Java z uporabo naprednih funkcij, kot so sledovi skladov, vzroki in veriženje izjem, poskusite -z viri, večkratni ulov, končni ponovni met in hoja v kupu.

Upoštevajte, da so primeri kode v tej vadnici združljivi z JDK 12.

prenos Prenesite kodo Prenesite izvorno kodo, na primer programe v tej vadnici. Ustvaril Jeff Friesen za JavaWorld.

Obravnava izjem v JDK 1.0 in 1.4: Sledi skladov

Vsak JVM nit (pot izvedbe) je povezana z sklad ki je ustvarjen, ko je nit ustvarjena. Ta podatkovna struktura je razdeljena na okvirji, ki so podatkovne strukture, povezane s klici metode. Iz tega razloga se sklad vsake niti pogosto imenuje a niz klicev metode.

Ob vsakem klicu metode se ustvari nov okvir. Vsak okvir shrani lokalne spremenljivke, spremenljivke parametrov (ki vsebujejo argumente, posredovane metodi), informacije za vrnitev klicne metode, prostor za shranjevanje vrnjene vrednosti, informacije, ki so koristne pri pošiljanju izjeme itd.

A sled sklada (znan tudi kot povratne sledi sklada) je poročilo o aktivnih okvirih skladov v določenem trenutku med izvajanjem niti. Java Mečljivo razred (v java.lang paket) ponuja metode za tiskanje sledov skladov, izpolnjevanje sledov skladov in dostop do elementov sledov sklada.

Tiskanje sledi sklada

Ko vrgel izjava vrže metanje, najprej poišče primernega ulov v izvedbeni metodi. Če ga ne najdete, se sprosti niz klicev metode in poišče najbližjega ulov blok, ki lahko obravnava izjemo. Če ga ne najdete, se JVM konča z ustreznim sporočilom. Razmislite o seznamu 1.

Seznam 1. PrintStackTraceDemo.java (različica 1)

import java.io.IOException; javni razred PrintStackTraceDemo {javna statična void main (String [] args) vrže IOException {metati nov IOException (); }}

Izmišljeni primer navedbe 1 ustvari a java.io.IOException predmet in ga vrže iz glavni () metoda. Ker glavni () ne obvladuje tega, kar bi lahko vrgli, in ker glavni () je metoda najvišje ravni, JVM konča s primernim sporočilom. Za to aplikacijo boste videli naslednje sporočilo:

Izjema v niti "main" java.io.IOException na PrintStackTraceDemo.main (PrintStackTraceDemo.java:7)

JVM to sporočilo odda s klicem Mečljivoje void printStackTrace () metoda, ki natisne sled sklada za priklic Mečljivo objekt v standardnem toku napak. Prva vrstica prikazuje rezultat klica meta toString () metoda. V naslednji vrstici so prikazani podatki, ki jih je predhodno zabeležil fillInStackTrace () (obravnavano v kratkem).

Dodatne metode sledenja skladov tiska

Mečljivoje preobremenjen void printStackTrace (PrintStream ps) in void printStackTrace (PrintWriter pw) metode izpišejo sled sklada v določen tok ali zapisovalnik.

Sled sklada razkrije izvorno datoteko in številko vrstice, kjer je bil ustvarjen metanje. V tem primeru je bil ustvarjen v vrstici 7 PrintStackTrace.java izvorna datoteka.

Lahko se sklicujete printStackTrace () neposredno, običajno iz a ulov blok. Na primer, razmislite o drugi različici PrintStackTraceDemo aplikacijo.

Seznam 2. PrintStackTraceDemo.java (različica 2)

import java.io.IOException; javni razred PrintStackTraceDemo {public static void main (String [] args) vrže IOException {try {a (); } catch (IOException ioe) {ioe.printStackTrace (); }} static void a () vrže IOException {b (); } static void b () vrže IOException {vrže novo IOException (); }}

Seznam 2 razkriva a glavni () metoda, ki prikliče metodo a (), ki prikliče metodo b (). Metoda b () vrže IOException objekt JVM, ki odvije niz klicev metode, dokler ne najde glavni ()je ulov blok, ki lahko obravnava izjemo. Izjema se obravnava s klicem printStackTrace () na metanju. Ta metoda ustvari naslednji rezultat:

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

printStackTrace () ne izpiše imena niti. Namesto tega prikliče toString () vrniti v celoti usposobljeno ime razreda za metanje (java.io.IOException), ki se izpiše v prvi vrstici. Nato izpiše hierarhijo klica metode: nazadnje poklicana metoda (b ()) je na vrhu in glavni () je na dnu.

Katero vrstico identificira sled sklada?

Sled sklada identificira vrstico, v kateri je ustvarjena možnost metanja. Ne identificira črte, kamor se meče (preko vrgel), razen če je metanje vrženo na isto črto, kjer je ustvarjeno.

Izpolnjevanje sledi sklada

Mečljivo izjavlja a Dopolnilni fillInStackTrace () metoda, ki zapolni sled izvedbenega sklada. V priklicu Mečljivo objekt zapiše informacije o trenutnem stanju okvirov skladov trenutne niti. Razmislite o seznamu 3.

Seznam 3. FillInStackTraceDemo.java (različica 1)

import java.io.IOException; javni razred FillInStackTraceDemo {public static void main (String [] args) vrže IOException {try {a (); } catch (IOException ioe) {ioe.printStackTrace (); System.out.println (); throw (IOException) ioe.fillInStackTrace (); }} static void a () vrže IOException {b (); } static void b () vrže IOException {vrže novo IOException (); }}

Glavna razlika med seznamom 3 in seznamom 2 je ulov blokov throw (IOException) ioe.fillInStackTrace (); izjavo. Ta izjava nadomešča ioe's stack stack, po katerem se metanje znova vrže. Upoštevajte ta izhod:

java.io. FillInStackTraceDemo.main (FillInStackTraceDemo.java:15)

Namesto ponavljanja začetne sledi sklada, ki določa lokacijo, kjer je IOException je bil ustvarjen objekt, sled drugega sklada razkrije lokacijo ioe.fillInStackTrace ().

Metalni konstruktorji in fillInStackTrace ()

Vsak od Mečljivoprikliče konstruktor fillInStackTrace (). Naslednji konstruktor (uveden v JDK 7) te metode ne bo sprožil, ko ga prenesete napačno do writableStackTrace:

Throwable (sporočilo v nizu, vzrok za Throwable, logično omogočanjeSuppression, logično writableStackTrace)

fillInStackTrace () prikliče izvorno metodo, ki se spušča po nizu metod-klicev trenutne niti za izdelavo sledi sklada. Ta sprehod je drag in lahko vpliva na uspešnost, če se pojavlja prepogosto.

Če naletite na situacijo (morda z vdelano napravo), kjer je zmogljivost ključnega pomena, lahko preprečite, da bi bila sled sklada zgrajena s preglasitvijo fillInStackTrace (). Oglejte si seznam 4.

Seznam 4. FillInStackTraceDemo.java (različica 2)

{public static void main (String [] args) vrže NoStackTraceException {try {a (); } catch (NoStackTraceException nste) {nste.printStackTrace (); }} statična praznina a () vrže NoStackTraceException {b (); } static void b () vrže NoStackTraceException {vrzi novo NoStackTraceException (); }} razred NoStackTraceException razširja Exception {@Override javno sinhronizirano Throwable fillInStackTrace () {return this; }}

Seznam 4 uvaja NoStackTraceException. Ta razveljavljeni razred izjem po meri preveri fillInStackTrace () vrniti to - sklic na sklic Mečljivo. Ta program ustvari naslednji rezultat:

NoStackTraceException

Komentirajte razveljavitev fillInStackTrace () in opazili boste naslednji izhod:

NoStackTraceException na FillInStackTraceDemo.b (FillInStackTraceDemo.java:22) na FillInStackTraceDemo.a (FillInStackTraceDemo.java:17) na FillInStackTraceDemo.main (FillInStackTraceDraceDemoceraTraceDraceDraceDemo.

Dostop do elementov sledenja sklada

Včasih boste morali dostopati do elementov sledov sklada, da boste lahko izluščili podrobnosti, potrebne za beleženje, ugotavljanje vira uhajanja virov in druge namene. The printStackTrace () in fillInStackTrace () metode ne podpirajo te naloge, vendar je predstavljen JDK 1.4 java.lang.StackTraceElement in njegove metode v ta namen.

The java.lang.StackTraceElement class opisuje element, ki predstavlja okvir sklada v sledu sklada. Njegove metode lahko uporabimo za vrnitev popolnoma kvalificiranega imena razreda, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada, skupaj z drugimi koristnimi informacijami. Tu so glavne metode:

  • String getClassName () vrne popolnoma kvalificirano ime razreda, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada.
  • String getFileName () vrne ime izvorne datoteke, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada.
  • int getLineNumber () vrne številko vrstice izvorne vrstice, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada.
  • String getMethodName () vrne ime metode, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada.
  • logična isNativeMethod () vrne prav ko je metoda, ki vsebuje izvršilno točko, ki jo predstavlja ta element sledenja sklada, izvorna metoda.

JDK 1.4 je predstavil tudi StackTraceElement [] getStackTrace () metoda do java.lang.Nit in Mečljivo razredih. Ta metoda vrne matriko elementov sledenja skladov, ki predstavljajo dump sklada sklicevalne niti, in zagotavlja programski dostop do informacij o sledovanju skladov, ki jih natisne printStackTrace ().

Seznam 5 prikazuje StackTraceElement in getStackTrace ().

Seznam 5. StackTraceElementDemo.java (različica 1)

import java.io.IOException; javni razred StackTraceElementDemo {public static void main (String [] args) vrže IOException {try {a (); } catch (IOException ioe) {StackTraceElement [] stackTrace = ioe.getStackTrace (); for (int i = 0; i <stackTrace.length; i ++) {System.err.println ("Izjema, vržena iz" + stackTrace [i] .getMethodName () + "v razredu" + stackTrace [i] .getClassName () + "on line" + stackTrace [i] .getLineNumber () + "datoteke" + stackTrace [i] .getFileName ()); System.err.println (); }}} static void a () vrže IOException {b (); } static void b () vrže IOException {vrže novo IOException (); }}

Ko zaženete to aplikacijo, boste opazili naslednje rezultate:

Izjema, vržena iz b v razredu StackTraceElementDemo v vrstici 33 datoteke StackTraceElementDemo.java Izjema, vržena iz razreda StackTraceElementDemo v vrstici 28 datoteke StackTraceElementDemo.java Izjema, vržena iz glavnega v razredu StackTraceElementDemo v vrstici 9 datoteke StackTraceElementDjava

Končno je JDK 1.4 predstavil setStackTrace () metoda za Mečljivo. Ta metoda je zasnovana za uporabo ogrodja oddaljenega klica postopka (RPC) in drugih naprednih sistemov, kar omogoča odjemalcu, da preglasi privzeto sled sklada, ki ga ustvari fillInStackTrace () ko je zgrajen metalec.

Prej sem pokazal, kako preglasiti fillInStackTrace () za preprečitev izdelave sledi sklada. Namesto tega lahko z uporabo namestite novo sled sklada StackTraceElement in setStackTrace (). Ustvari matriko StackTraceElement predmeti, inicializirani z naslednjim konstruktorjem, in posredujejo to polje setStackTrace ():

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

Seznam 6 prikazuje StackTraceElement in setStackTrace ().