image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Introduction

Caractéristiques de Java

Quelques conseils pour une programmation plus sûre

Usage des esceptions

Error

Débordement de pile ou surcharge du tas ?

package fr.upem.jacosa.safety;

public class Overflowing
{
	public static void recursiveMethod(int k)
	{
		byte[] tab = new byte[k];
		recursiveMethod(k);
		tab[0] = 1;
	}
	
	public static void main(String[] args)
	{
		int k = Integer.parseInt(args[0]);
		recursiveMethod(k);
	}
}

Cela dépend de k, de la taille de la pile et de la mémoire allouée pour le tas

StackOverflowError et OutOfMemoryError

StackOverflowError

(Presque) toujours une erreur de programmation généralement liée à :

Toutefois le changement de la taille de la pile est possible : java -Xss10M ... pour une pile de 10 Mo par exemple

OutOfMemoryError

Programme trop gourmand en allocation mémoire sur le tas

Solutions :

Classe Exception

Classe RuntimeException : la mère de (presque) toutes les exceptions non-vérifiées

NullPointerException

Les exceptions les plus fréquentes

D'après Takipi, les exceptions les plus fréquentes interrompant un programme sont :

Vie et mort d'une exception

try-catch-finally

try {
	// Appel de méthodes pouvant lever des exceptions
} catch (Exception1 e1)
{
	// Pour traiter les exceptions de type Exception1
} catch (Exception2 e2)
{
	// Pour traiter les exceptions de type Exception2
	// Exception2 peut être un ancêtre de Exception1 
	// (exception plus générale)
	// Par contre Exception2 NE PEUT PAS être 
	// un descendant de Exception1
	// (l'exception est capturée 
	// par le premier catch pouvant la capturer)
} finally
{
	// Le code dans le bloc finally 
	// est executé inconditionnellement
	// qu'il y ait eu levée d'exception ou non
	// Utile pour ne pas oublier de libérer des ressources
}

Try with resources

// Il est possible d'instantier des objets au début du try
// qui seront fermés automatiquement par l'appel de leur méthode close()
// dans l'ordre inverse de leur déclaration
// Les classes concernées doivent implanter l'interface AutoCloseable
try (InputStream is = new FileInputStream(monFichier); 
	Scanner s = new Scanner(is);)
{
	int i = s.nextInt();
	System.out.println(i);
} catch (IOException 
	| InputMismatchException 
	| NoSuchElementException e)
{
	// Il est possible de regrouper 
	// plusieurs types d'exceptions dans un même catch
	// e a pour type statique 
	// l'ancêtre commun de tous ces types (ici Exception)
	// catch est executé après avoir fermé automatiquement
	// les ressources
	System.err.println(
		"L'entier n'a pas pu être lu à cause d'une exception: " 
		+ e.getMessage());
} finally
{
	// Bloc finally exécuté
	// après la fermeture des ressources
	// et l'éventuel catch si exception
}

Exceptions vérifiées et non-vérifiées

Toutes les exceptions sont vérifiées sauf celles héritant :

Une méthode pouvant lever une exception vérifiée TypeException doit :

Créer ses exceptions

L'ampoule cassée

public class BrokenBulbException extends IllegalStateException
{
	private final long since; // When the bulb was broken (milliseconds since the Unix epoch)
	
	public BrokenBulbException(String message, Throwable cause, long since)
	{
		super(message, cause);
		this.since = since;
	}
	
	public long getBrokenDate() { return since; }
}
...
public class LimitedBulb
{
	private boolean alive;
	private long deathDate;
	...
	public void switchBulb()
	{
		updateLiveness();
		if (!alive)
			throw new BrokenBulbException("The bulb is broken", null, deathDate);
		...
	}
}