Dai un'occhiata agli errori di runtime Java

Feb 26 2023
Una rapida panoramica degli errori di runtime Java · Cosa sono gli errori di runtime in Java?· Errore di runtime VS errore di compilazione· Tipi di errori di runtime· Come appare l'errore di runtime?· Devo lanciare errori di runtime· Cosa è successo quando non t cattura un'eccezione di runtime · Esempio di errore di runtime Cosa sono gli errori di runtime in Java? Gli errori che si verificano al momento dell'esecuzione del programma sono indicati come errori di runtime. Questi tipi di errori non possono essere rilevati al momento della compilazione poiché non c'è niente di sbagliato nella loro sintassi.

Una rapida panoramica degli errori di runtime Java

· Cosa sono gli errori di runtime in Java?
· Errore di runtime VS Errore in fase di compilazione
· Tipi di errori di runtime
· Come appare l'errore di runtime?
· Devo generare errori di runtime
· Cosa è successo quando non si rileva un'eccezione di runtime
· Esempio di errore di runtime

Cosa sono gli errori di runtime in Java?

Gli errori che si verificano al momento dell'esecuzione del programma sono indicati come errori di runtime. Questi tipi di errori non possono essere rilevati al momento della compilazione poiché non c'è niente di sbagliato nella loro sintassi. Quindi gli errori di runtime si verificano quando il programma è stato compilato con successo senza dare errori e creando un file ".class". Tuttavia, il programma non viene eseguito correttamente. Questi errori vengono rilevati in fase di esecuzione o al momento dell'esecuzione del programma.

Il compilatore Java non rileva gli errori di runtime perché il compilatore Java non dispone di alcuna tecnica per rilevare questi errori poiché non dispone di tutte le informazioni di runtime disponibili. Gli errori di runtime vengono rilevati da Java Virtual Machine (JVM) quando il programma è in esecuzione.

Questi errori di runtime sono chiamati eccezioni e terminano il programma in modo anomalo, fornendo una dichiarazione di errore.

Le eccezioni sono errori generati in fase di esecuzione. Possiamo utilizzare tecniche di gestione delle eccezioni in Java per gestire questi errori di runtime. Nella gestione delle eccezioni, il pezzo di codice che il programmatore ritiene possa produrre l'errore viene inserito nel blocco try e il programmatore può rilevare l'errore all'interno del blocco catch.

Errore di runtime VS Errore in fase di compilazione

Un errore in fase di compilazione si riferisce generalmente agli errori che corrispondono alla semantica o alla sintassi. Un errore di runtime si riferisce all'errore che incontriamo durante l'esecuzione del codice durante il runtime . Possiamo facilmente correggere un errore in fase di compilazione durante lo sviluppo del codice. Un compilatore non può identificare un errore di runtime.

Rilevamento

I compilatori possono rilevare facilmente gli errori in fase di compilazione durante lo sviluppo del codice. Un compilatore non può rilevare facilmente un errore in fase di esecuzione. Pertanto, dobbiamo identificarlo durante l'esecuzione del codice.

Riferimento

Un errore in fase di compilazione si riferisce generalmente agli errori che corrispondono alla semantica o alla sintassi. Un errore di runtime si riferisce all'errore che non viene rilevato dal compilatore ma che incontriamo durante l'esecuzione del codice (durante il runtime).

impatto

Gli errori in fase di compilazione sono errori semantici o di sintassi , impediscono l'esecuzione (compilazione) del codice poiché rileva alcuni errori di sintassi. Gli errori di runtime di WHEARES impediscono l'esecuzione completa del codice.

Fissazione

Possiamo facilmente correggere un errore in fase di compilazione durante lo sviluppo del codice. Un compilatore non può identificare un errore in fase di esecuzione. Ma possiamo risolverlo dopo l'esecuzione del codice e l'identificazione del codice in precedenza.

Tipi di errori di runtime

Esistono diversi tipi di errori di runtime che possiamo incontrare al momento dell'esecuzione del programma. Di seguito sono elencati alcuni errori di runtime riscontrati di frequente:

Errori di immissione dati: errori di input-output

Esistono innumerevoli modi in cui l'input dell'utente può danneggiare un'applicazione.

Su una bacheca dei commenti basata su HTML, un utente a cui è consentito inviare innocentemente un segno minore di (<) o maggiore di (>) non codificato ha il potenziale per rovinare completamente la capacità di visualizzazione di quella pagina web. Allo stesso modo, i sistemi di elaborazione del testo costruiti per aspettarsi tutti gli input in formato ASCII possono terminare prematuramente se ricevono emoji o input di caratteri non standard.

Più nefasto, un vettore di attacco preferito dagli hacker è l'iniezione SQL , che nasconde una query di database eseguibile dannosa all'interno di un campo di input altrimenti innocuo. Questo non solo può causare il fallimento di un'applicazione, ma può anche cedere il controllo dell'intero livello di dati.

Il processo di sanificazione dell'input, o pulizia dei dati , converte l'ampio spettro di dati che potrebbero essere potenzialmente immessi nelle applicazioni in un intervallo sicuro di valori comprensibili da un programma. L'uso di tali librerie aiuta a mitigare gli errori di runtime causati da errori di sanificazione dell'input.

I framework Java più diffusi come Apache BVal e Hibernate Validator eseguono una semplice pulizia dell'input basata su annotazioni e si integrano facilmente in qualsiasi applicazione basata su Java.

Logica mal implementata

Solo perché il codice viene compilato non significa che funzioni correttamente. Il codice spesso contiene problemi logici che causano il fallimento di un'applicazione in fase di esecuzione.

Java contiene un costrutto integrato per gestire una classe di errori di runtime comuni relativi al codice, chiamata RuntimeException o eccezione non verificata. Java 17 definisce 78 errori di questo tipo solo nell'SDK e altri progetti e framework definiscono inoltre i propri errori RuntimeException.

  • RuntimeException
  • ArrayIndexOutOfBoundException
  • ConcurrentModificationException
  • ClassCastException
  • …

Per lo meno, ogni applicazione dovrebbe includere un cablaggio di eccezione generico in grado di rilevare ogni possibile RuntimeException, registrare l'errore e consentire la morte del thread di esecuzione problematico anziché interrompere l'intera applicazione.

Risorse di runtime insufficienti

Gli sviluppatori di software non si assumono la colpa per ogni tipo di errore di runtime che si verifica. Molti errori di runtime in Java implicano limitazioni delle risorse causate da problemi con l'infrastruttura sottostante. Gli esempi includono: timeout di rete, condizioni di memoria insufficiente , utilizzo eccessivo della CPU o impossibilità di pianificare un thread sul processore.

Un modo per evitare errori di runtime correlati alle risorse consiste nell'usare uno strumento di test del carico, ad esempio JMeter o LoadRunner, nella pipeline CI/CD di un'applicazione. Se questi strumenti rilevano un possibile problema di prestazioni, possono arrestare l'applicazione prima che si sposti ulteriormente lungo la pipeline verso la distribuzione di produzione.

Il carico di alcune applicazioni varia drasticamente. Ad esempio, un'app di servizi finanziari può vedere un carico costante per la maggior parte del tempo ma essere estremamente occupata alla fine della giornata di negoziazione. Un servizio fiscale potrebbe raggiungere un picco di carico prima della scadenza del deposito, ma avere un carico relativamente basso per il resto dell'anno.

I team DevOps devono monitorare le proprie metriche prestazionali con strumenti per rilevare preventivamente e mitigare gli errori di runtime relativi alle risorse. Esempi di tali strumenti includono JDK Flight Recorder e Java Mission Control .

Per le applicazioni con carichi di lavoro completamente imprevedibili, utilizza la tecnologia di bilanciamento del carico basata su cloud per allocare le risorse in modo elastico. Ciò elimina sia le risorse sottoallocate sia la trappola dell'acquisto di hardware costoso e raramente utilizzato.

Configurazione delle risorse esterne

Le applicazioni aziendali raramente esistono in una bolla isolata. In genere interagiscono con qualsiasi cosa, dai database NoSQL e dai sistemi relazionali alle code Kafka e alle API RESTful. Sfortunatamente, se la tua applicazione non è in grado di connettersi a un sistema esterno richiesto, ciò si traduce inevitabilmente in un errore di runtime.

Una risorsa esterna può causare un errore di runtime se si verifica una delle seguenti situazioni senza un aggiornamento corrispondente al programma chiamante:

  • un indirizzo IP cambia;
  • modifica delle credenziali;
  • modifica della configurazione del firewall; O
  • il sistema esterno va fuori servizio per manutenzione.

Allo stesso modo, gli strumenti di ingegneria del caos terminano in modo casuale i processi da cui dipende un'applicazione. Tali strumenti costringono gli sviluppatori a scrivere codice che rimane reattivo e resiliente anche quando i sistemi esterni falliscono.

Il problema intrinseco delle risorse esterne è che gli sviluppatori non possono controllarle, ma possono controllare il modo in cui un'applicazione risponde quando tali risorse esterne falliscono. Anticipa gli errori di runtime generati dai sistemi che non controlli e scrivi applicazioni che rispondono correttamente quando i sistemi esterni falliscono.

Vulnerabilità della libreria di terze parti

Qualsiasi applicazione aziendale non banale include dozzine di dipendenze da librerie di terze parti per eseguire funzioni quali registrazione, monitoraggio, convalida dell'input, gestione dei moduli e altro ancora.

Sfortunatamente, qualsiasi bug in una libreria di terze parti diventa un bug nell'applicazione che distribuisci. Ciò è diventato spiacevolmente reale per il mondo Java nel dicembre 2021, poiché un difetto di iniezione LDAP nella libreria Log4j 2 ampiamente utilizzata ha costretto le JVM di tutto il mondo ad andare offline.

Un modo per mitigare la possibilità che le dipendenze software introducano errori di runtime nelle applicazioni è utilizzare solo librerie attendibili di organizzazioni come Apache o Eclipse.

Un'altra misura protettiva consiste nell'aggiornare regolarmente le dipendenze di un'applicazione all'ultima versione non appena gli aggiornamenti diventano disponibili.

Infine, sii consapevole delle dipendenze secondarie o terziarie - quelle su cui si basano le tue stesse dipendenze primarie - e sii consapevole di eventuali rischi che comportano.

Nel mondo dello sviluppo software, "perfetto" è nemico di "fatto". Nessun programma è immune dalla minaccia di un errore di runtime imprevisto. Tuttavia, quando gli sviluppatori aziendali aumentano la consapevolezza delle possibili cause e adottano misure per mitigare potenziali minacce, possono creare software che riduca al minimo la probabilità di riscontrare un errore di runtime.

Come viene visualizzato l'errore di runtime?

Congratulazioni! Se il tuo prompt dei comandi è simile a questo:

Quindi hai compilato con successo il tuo programma in bytecode Java, il che significa che non ci sono stati problemi sintattici con il tuo codice! Ma, come suggerisce il nome del file, quando eseguiamo questo programma:

Ora abbiamo riscontrato un errore di runtime. Gli errori di runtime generalmente si verificano quando c'è qualcosa di logicamente errato nel codice. Questo documento spiegherà come leggere e correggere gli errori di runtime.

Ecco le parti principali dell'errore di runtime

Eccezione nel thread "principale" : questa parte appare per la maggior parte degli errori di runtime. Ti dice solo che l'eccezione si è verificata nel metodo principale, che dovrebbe accadere sempre.

java.lang.ArrayIndexOutOfBoundsException: 5 : questo è l'errore che si è verificato. Il nome dell'errore generalmente ti darà un'idea di cosa potrebbe essere successo. In questo caso, sappiamo che si tratta di array e di uscire dallo spazio assegnato per un array.

at RunTimeErrors.main(RunTimeErrors.java:10) : Questa è chiamata traccia dello stack, che indica l'elenco dei metodi in esecuzione quando si è verificato l'errore.

  • RunTimeErrors.main ci dice che questo errore si è verificato all'interno del metodo principale della classe RunTimeErrors.
  • RunTimeErrors.java:10 ci dice il file in cui si è verificato e in quale riga è accaduto. In questo caso, è successo nella nostra classe principale alla riga 10 .

A volte è necessario eseguire un controllo per decidere se lanciare un'eccezione di runtime se il sistema non può farlo da solo, spesso quando si lavora con IllegalArgumentException, ma la maggior parte delle volte non è necessario eseguire un controllo perché fa parte di il controllo di runtime standard che Java esegue per te.

prendiamo NullPointerException come esempio:

if(t == null) 
 throw new NullPointerException();

if(t != null) {
  // work with t reference
}

Cosa succede quando non rilevi le eccezioni di runtime? Dal momento che il compilatore non impone specifiche di eccezione per questi, è abbastanza plausibile che una RuntimeException possa filtrare fino al tuo metodo main() senza essere catturata. Per vedere cosa succede in questo caso, prova il seguente esempio:

//: exceptions/NeverCaught.java 
// Ignoring RuntimeExceptions. 
// {ThrowsException} 
public class NeverCaught { 
 static void f() { 
 throw new RuntimeException("From f()"); 
 } 
 static void g() { 
 f(); 
 } 
 public static void main(String[] args) { 
 g(); 
 } 
} ///:~

Exception in thread "main" Java.lang.RuntimeException: From f() 
    at NeverCaught.f(NeverCaught.Java:7) 
    at NeverCaught.g(NeverCaught.Java:10) 
    at NeverCaught.main(NeverCaught.Java:13)

Tieni presente che solo le eccezioni di tipo RuntimeException (e le sottoclassi) possono essere ignorate nella codifica, poiché il compilatore impone con attenzione la gestione di tutte le eccezioni verificate. Il ragionamento è che una RuntimeException rappresenta un errore di programmazione, che è:

Un errore che non puoi prevedere. Ad esempio, un riferimento nullo al di fuori del tuo controllo.

Un errore che tu, come programmatore, avresti dovuto controllare nel tuo codice (come ArraylndexOutOfBoundsException dove avresti dovuto prestare attenzione alla dimensione dell'array). Un'eccezione che si verifica dal punto n. 1 diventa spesso un problema per il punto

Puoi vedere quale enorme vantaggio è avere eccezioni in questo caso, poiché aiutano nel processo di debug.

È interessante notare che non è possibile classificare la gestione delle eccezioni Java come uno strumento monouso. Sì, è progettato per gestire quei fastidiosi errori di runtime che si verificheranno a causa di forze al di fuori del controllo del codice, ma è anche essenziale per alcuni tipi di bug di programmazione che il compilatore non è in grado di rilevare.

Esempio di errore di runtime

public class Temp {
public static void main(String[] args) {
  Temp t = initT();
  
  t.foo("Hi");
  
 }
 private static Temp initT() {
  return null;
 }
 public void foo(String s) {
  System.out.println(s.toLowerCase());
 }
}

Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:7)

C'è un intero gruppo di tipi di eccezioni che rientrano in questa categoria. Vengono sempre generati automaticamente da Java e non è necessario includerli nelle specifiche dell'eccezione. Abbastanza convenientemente, sono tutti raggruppati mettendoli sotto un'unica classe base chiamata RuntimeException , che è un perfetto esempio di ereditarietà: stabilisce una famiglia di tipi che hanno alcune caratteristiche e comportamenti in comune. Inoltre, non è mai necessario scrivere una specifica di eccezione che dica che un metodo potrebbe lanciare una RuntimeException (o qualsiasi tipo ereditato da RuntimeException ), perché sono eccezioni non controllate. Poiché indicano bug, di solito non si rileva un'eccezione RuntimeException- viene gestito automaticamente. Se sei stato costretto a controllare RuntimeExceptions , il tuo codice potrebbe diventare troppo disordinato. Anche se in genere non rilevi RuntimeExceptions , nei tuoi pacchetti potresti scegliere di lanciare alcune delle RuntimeExceptions .

Vedere Le eccezioni di runtime più comuni

Buon apprendimento

Unisciti al gruppo Mouad Oumous Java WhatsApp ISCRIVITI

Unisciti al canale Telegram di Mouad Oumous ISCRIVITI

Sostieni la nostra pubblicazione seguendola

GraphQL con Spring Boot Gli errori di runtime Java più comuni Introduzione a Spring Boot: un tutorial completo per principianti 10 modi semplici ma efficaci per migliorare la qualità della vita Domanda di intervista basata sul flusso Java8 più comune - Parte finale I Guadagna $ 300 scrivendo un libro in 2 giorni: ecco come cos'è il concatenamento di eccezioni in Java | Gestione delle eccezioni Come creare un semplice progetto Quarkus con l'integrazione del database