control de excepciones - Escuela de Ingeniería Industrial

Anuncio
Introducción
™ Una excepción es un evento que ocurre durante la
ejecución de un programa, y que interrumpe su flujo de
control normal. Normalmente se encuentran asociadas a
“errores”.
™ Los errores pueden tener distintos orígenes: falla del disco
duro, problemas en la red, problemas de programación (ej.
división por cero), etc.
Java: control de excepciones
Franco Guidi Polanco
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile
fguidi@ucv.cl
Actualización: 07 de marzo de 2007
Franco Guidi Polanco
Detección de errores
™ Un caso de división por cero:
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
return x/y;
}
}
™ El objeto excepción contiene información relativa al error, incluyendo el
tipo del mismo y el estado del programa al momento de haberse
producido.
Franco Guidi Polanco
09-03-2007
2
Ejemplo 1
™ Cuando ocurre un error durante la ejecución de un método en Java se
genera un objeto excepción que es enviado al ambiente de ejecución. El
flujo de control normal del programa es interrumpido.
Excepción
Stack métodos
™ Cuando se genera el objeto excepción,
el ambiente de ejecución busca
en el stack de llamadas a métodos
alguno que sea capaz de manejar
la excepción (exception handler).
Si no lo encuentra, la JVM se hace cargo
de él, y el programa termina con
un mensaje de error.
09-03-2007
método n
…
método 2
método 1
JVM
public class Division{
public static void main(String[] arg) {
Par par = new Par( 100, 0 );
par.divide();
System.out.println(“Fin programa”);
}
}
3
Franco Guidi Polanco
09-03-2007
Clase Par, recibe dos
números enteros
y permite obtener el
cuociente entre ellos
El objeto de la clase Par
realizará una división
por cero
4
Ejemplo 1: Stack de llamadas a métodos
Ejecución del ejemplo 1
™ El método main invoca al método divide del objeto de la clase Par.
™ Durante la ejecución del método divide se genera una excepción.
...
return x/y;
...
...
par.divide();
...
divide
main
™ Clase de excepción:
(y = 0)
ƒ java.lang.ArithmeticException
™ Información:
ƒ / by zero (división por cero)
™ Stack de llamadas de métodos:
ƒ 1. Método divide de la clase Par (archivo Par.java, línea 11)
Java Virtual Machine
Franco Guidi Polanco
…llamado por…
ƒ 2. Método main de la clase Division (archivo Division.java, línea 6)
09-03-2007
5
La jerarquía de excepciones
09-03-2007
6
Opciones en el control de excepciones
™ Frente a un determinado tipo de excepción un método
puede:
Object
ƒ Lanzar la excepción fuera de él, para traspasar al método
invocante la responsabilidad de tratar la excepción; o en caso de
ser el primer método del stack de llamadas, traspasar la
responsabilidad a la JVM.
ƒ Capturar la excepción, y proveer un flujo de control alternativo.
Throwable
Error
Franco Guidi Polanco
Exception
Excepción
…
RuntimeException
Stack
métodos
…
…
Franco Guidi Polanco
09-03-2007
divide
main
JVM
7
Franco Guidi Polanco
09-03-2007
8
Control de excepciones: lanzamiento de una excepción
(cont.)
Control de excepciones: lanzamiento de una excepción
™ Un ejemplo clásico: lectura de datos de la consola
™ Para indicar que un método traspasará la responsabilidad
del control de excepciones al método llamante, se debe
usar la cláusula throws en la declaración del método,
seguida por el nombre de la excepción:
import java.io.* ;
public class Factorial {
public static void main( String arg[ ] ) throws IOException {
int número=0, i=1, fact=1;
BufferedReader lector = new BufferedReader( new InputStreamReader( System.in ) );
String ingresado=null;
System.out.println( "Ingrese número para cálculo de factorial: " );
ingresado = lector.readLine( );
número = Integer.parseInt( ingresado );
while( i <= número ) {
fact = fact * i;
i++;
}
System.out.println( "El factorial de " + número + " es " + fact );
} // Fin método main
} // Fin clase
™ Ejemplo:
Nombre
excepción
public boolean startPlaying() throws SoundException {
...
}
Franco Guidi Polanco
09-03-2007
9
Control de excepciones: captura de una excepción
Franco Guidi Polanco
™ Formato general:
El tipo de excepción
(Tipo_Excepción1,
Tipo_Excepción2, etc.)
representa la clase de
excepción que se puede
generar en el bloque try
que interesa capturar y
controlar.
ƒ El bloque try debe incluir las instrucciones que pueden generar la
excepción que se desea manejar. Debe ser seguido por al menos
un bloque catch o un bloque finally.
ƒ El bloque catch debe seguir al bloque try, y debe contener las
instrucciones que serán ejecutadas en caso de generarse una
excepción.
Al producirse una
excepción sólo uno de
los bloques catch será
ejecutado
ƒ El bloque finally incluye las instrucciones que deberán
ejecutarse independientemente de la generación (o ausencia) de
una excepción (normalmente usados para liberar recursos).
El orden de los catch es
importante: las subclases
de excepciones deben ser
especificadas antes de
sus superclases
09-03-2007
10
Control de excepciones: captura de una excepción (cont.)
™ Las excepciones pueden ser capturadas y manejadas
usando bloques try, catch y finally (operan en
conjunto)
Franco Guidi Polanco
09-03-2007
11
Franco Guidi Polanco
try {
}
}
}
}
}
// instrucciones que pueden fallar
…
catch (Tipo_excepción1 nombre_variable){
// instrucciones a ejecutar si se produce
// una excepción tipo 1
…
catch (Tipo_excepción2 nombre_variable){
// instrucciones a ejecutar si se produce
// una excepción tipo 2
…
catch (Tipo_excepciónN nombre_variable){
// instrucciones a ejecutar si se produce
// una excepción tipo N
…
finally{
// instrucciones a ejecutar siempre
09-03-2007
12
Control de excepciones: captura de una excepción (cont.)
™ (Nuevamente) el ejemplo clásico:
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
try{
return x/y;
}catch(ArithmeticException e){
return 999999999;
}
}
}
import java.io.* ;
public class Factorial {
public static void main( String arg[ ] ){
int número=0, i=1, fact=1;
BufferedReader lector = new BufferedReader( new InputStreamReader( System.in ) );
String ingresado=null;
System.out.println( "Ingrese número para cálculo de factorial: " );
try {
ingresado = lector.readLine( );
número = Integer.parseInt( ingresado );
while( i <= número ) {
fact = fact * i;
i++;
System.out.println( "El factorial de " + número + " es " + fact );
}
} catch( IOException e ) {
System.out.println( "Error de input." );
}
} // Fin método main
} // Fin clase
Franco Guidi Polanco
09-03-2007
Ejemplo 2: captura de una excepción
™ En este caso la
excepción es
interceptada en el
método divide
Nota: en el ejemplo es
discutible la decisión de
retornar esta constante en
caso de error en la división
public class Division{
public static void main(String[] arg) {
Par par = new Par( 100, 0 );
int res = par.divide();
System.out.println( "El cuociente es: " + res );
}
}
13
Ejecución del ejemplo 2
Franco Guidi Polanco
09-03-2007
14
Información relacionada con la excepción
™ Toda instancia de excepción tiene un método
printStackTrace, que imprime el stack de llamadas de
métodos al momento de generarse.
™ A pesar del error el programa completa su ejecución
normalmente:
™ Este método puede ser utilizado para proporcionar
información relacionada con la excepción dentro del bloque
catch correspondiente:
try {
™ ¿Qué ocurre?
// instrucciones que pueden fallar
…
} catch (Tipo_excepción nombre_variable){
nombre_variable.printStackTrace();
}
ƒ La excepción se produce en el método divide() de la clase Par,
dentro del bloque try. Esta excepción es capturada en el bloque
catch, y el código escrito en este último es ejecutado.
Franco Guidi Polanco
09-03-2007
15
Franco Guidi Polanco
09-03-2007
16
Ejemplo 3: impresión de la información asociada a la
excepción
1 public class Par {
2
int x, y;
3
public Par(int x, int y ){
4
this.x = x;
5
this.y = y;
6
}
7
public int divide() {
8
try{
9
return x/y;
10
}catch(ArithmeticException e){
11
e.printStackTrace();
12
return 999999999;
13
}
14
}
15 }
Ejecución del ejemplo 3
™ El programa ahora indica el tipo de excepción y lugar
donde ésta se produjo:
™ El objeto excepción es
referenciado al interior
del bloque catch por
medio de la variable e
™ Se invoca el método
printStackTrace
sobre el objeto excepción
™ Notar que el programa termina su ejecución normalmente.
1 public class Division{
2
public static void main(String[] arg) {
3
Par par = new Par( 100, 0 );
4
int res = par.divide();
5
System.out.println( "El cuociente es: " + res );
6 }
7 }
Franco Guidi Polanco
09-03-2007
17
La clase RuntimeException
Franco Guidi Polanco
09-03-2007
18
La clase RuntimeException (cont.)
™ Ejemplo: ArithmeticException es subclase de
RuntimeException. Por tanto las siguientes
implementaciones de la clase Par son equivalentes:
™ Representa excepciones comunes que se presentan en la
JVM durante la ejecución de programas. Ejemplo:
NullPointerException.
™ Debido a la ubicuidad de este tipo de excepciones, el
compilador permite no especificar el mecanismo de control
de las RuntimeExceptions: cuando este mecanismo no
es especificado, estas excepciones serán lanzadas fuera del
método actual.
RuntimeException
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide()
throws ArithmeticException {
return x/y;
}
}
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
return x/y;
}
}
NullPointerException
Franco Guidi Polanco
09-03-2007
19
Franco Guidi Polanco
09-03-2007
20
Crear nuevas excepciones
Crear nuevas excepciones (cont.)
™ Ejemplo:
™ Se pueden crear nuevas excepciones extendiendo la clase
Exception o una de sus subclases.
™ La clase Exception ofrece distintos constructores que
pueden ser referenciados desde las subclases. Los más
utilizados son:
public class UnsupportedMediaException extends Exception{
public UnsupportedMediaException(){
super( “The selected media is not supported.” );
}
}
ƒ public Exception(): inicializa la excepción con valores de
default (mensaje nulo)
ƒ public Exception(String mensaje): inicializa la excepción
con el mensaje recibido como parámetro.
™ Convención: el nombre de las excepciones termina en la
palabra “Exception”
™ Nota: la clase RuntimeException también puede ser
extendida.
Franco Guidi Polanco
09-03-2007
21
Lanzamiento de una excepción
22
public class Test{
public static void main(String[] arg) throws UnsupportedMediaException {
Recorder r = new Recorder( "CD" );
r.saveOn( "DVD" );
System.out.println( "Saved." );
}
}
throw new NombreExcepción( parámetros_constructor )
™ Ejemplo:
public void saveData throws UnsupportedMediaException{
...
if( !isCompatible( requestedMedia ) )
throw new UnsupportedMediaException();
...
}
09-03-2007
09-03-2007
Ejemplo 4: creación y lanzamiento de excepciones
™ Una excepción puede ser lanzada en cualquier parte del
código usando la instrucción throw acompañada de la
referencia a un objeto excepción:
Franco Guidi Polanco
Franco Guidi Polanco
23
public class Recorder {
String media;
public Recorder( String mediaType ){
media = mediaType;
}
public void saveOn( String mediaType ) throws UnsupportedMediaException{
if( media.equals( mediaType ) )
System.out.println( "Saving." );
else
throw new UnsupportedMediaException();
}
}
public class UnsupportedMediaException extends Exception {
public UnsupportedMediaException() {
super( "The selected media is not supported" );
}
}
Franco Guidi Polanco
09-03-2007
24
Ejecución del ejemplo 4
Ejercicio
™La excepción definida se comporta como cualquier
otra excepción:
™ Se pide crear la clase Temperature, para registrar
temperaturas en grados Celsius (ºC) y Kelvin (ºK).
Una instancia de la clase deberá almacenará un valor de
temperatura y lo retornará en cualquiera de las escalas.
Para ello la clase deberá ofrecer los métodos setC y setK
para establecer valores en ºC y ºK, y los métodos getC y
getK para retornar los valores en ºC y ºK,
respectivamente.
Notar que no es físicamente posible admitir temperaturas
inferiores a los 0ºK, por lo tanto será necesario generar una
excepción (IllegalTemperatureException) cuando un
valor fuera de rango trate de ser ingresado.
Genere las clases indicadas, y una aplicación que permita
ingresar valores y visualizarlos.
Franco Guidi Polanco
09-03-2007
25
Discusión
Franco Guidi Polanco
09-03-2007
26
Excepciones: caso del Ariane 5
™Vuelo 501, 4 de Junio de 1996, autodestrucción en
H0 +39 :
™ Considere los siguientes ejemplos:
ƒ Una clase CuentaCorriente (que maneja una
cuenta bancaria) no debe admitir giros mayores que
el saldo disponible. En caso de ser inadmisible el
giro, éste podría ser impedido:
• Retornado false en el método que efectúa el giro.
• Generando una excepción en el método que efectúa el
giro.
ƒ En la clase Temperature del ejemplo anterior se
genera una excepción cuando se trata de establecer
una temperatura inválida. Alternativamente se podría
haber obviado la creación de la excepción, y haber
retornado falso en los métodos setK y setC.
™ ¿Cuándo conviene generar excepciones?
Costo: 500 millones de dólares
Franco Guidi Polanco
09-03-2007
27
Franco Guidi Polanco
09-03-2007
28
Excepciones: caso del Ariane 5 (cont.)
Excepciones: caso del Ariane 5 (cont.)
™Sistema de control de vuelo:
Reporte del equipo de investigación sobre la falla del vuelo 501:
Plataforma de
referencia inercial
™ Aproximadamente en el instante H0 +39 segundos, el Ariane 5 comenzó
a desintegrarse debido a esfuerzos aerodinámicos excesivos ocasionados
por un ángulo de ataque inapropiado. Esto condujo a la separación de
los propulsores auxiliares respecto del cuerpo principal de la nave, por lo
que se gatilló el mecanismo de autodestrucción del cohete.
Lecturas de giroscopios y acelerómetros
SRI-1
SRI-2
Bus de datos
OBC-1
OBC-2
SRI: Inertial
Reference System
™ Este ángulo de ataque resultó ser consecuencia de una completa
desalineación entre las toberas de los propulsores auxiliares y aquella del
motor principal.
OBC: On-Board
Computer
™ La desalineación de las toberas fue comandada por el OBC a partir de
información transmitida por el SRI-2. Parte de estos datos no contenían
información de vuelo, sino un patrón de diagnóstico del SRI, el cual fue
interpretado como información de vuelo.
Servo-válvulas y
actuadores hidráulicos
™ La razón por la cual el SRI-2 no envió datos reales es que la unidad se
había declarado en falla por una excepción de software.
MOTORES
Franco Guidi Polanco
09-03-2007
29
Excepciones: caso del Ariane 5 (cont.)
30
™ Comentarios:
™ La excepción interna en el software del SRI fue ocasionada durante la
ejecución de una instrucción de conversión de un valor en formato
punto flotante de 64 bits a entero con signo de 16 bits, en
circunstancias que el valor excedía la capacidad del tipo entero. La
operación de conversión no estaba protegida, aún cuando asignaciones
de variables similares sí lo estaban.
™ El valor que se intentó convertir correspondía a la magnitud de la
variable HB (desviación horizontal), significativa sólo durante la fase de
alineación previa al despegue. Sin embargo, esta función de cálculo se
mantuvo operativa durante 40 segundos tras el despegue por un
requerimiento en el diseño del Ariane 4, no presente en el Ariane 5 (el
diseño del SRI de ambas naves era en práctica idéntico).
™ La conversión del valor de la variable HB no estaba protegida porque el
Ariane 4 realizaba una trayectoria inicial distinta a la del Ariane 5, en la
cual dicha variable nunca tomaría valores fuera del rango esperado.
09-03-2007
09-03-2007
Excepciones: caso del Ariane 5 (cont.)
™ El OBC no pudo acceder al SRI-1 porque este se había desactivado
algunos milisegundos antes por la misma razón que el SRI-2.
Franco Guidi Polanco
Franco Guidi Polanco
31
ƒ La operación inválida generaba correctamente una excepción. Sin
embargo, el mecanismo de gestión de excepciones no fue diseñado
para responder adecuadamente.
ƒ El mecanismo de tolerancia a fallas del Ariane 5 estaba concebido
para tratar fallas aleatorias (por ej. malfuncionamiento del
hardware de uno de los computadores), no errores de diseño
(ambas SRI experimentaron el mismo comportamiento al momento
de producirse la falla).
ƒ El equipo de investigación sobre el accidente sugirió cambiar el
enfoque de desarrollo utilizado hasta entonces, “el software se
considera correcto hasta que se demuestra que falla”, por el
enfoque “se asume que el software es defectuoso hasta que, tras
aplicar métodos aceptados como buenas prácticas, se logre
demostrar que está correcto”.
Franco Guidi Polanco
09-03-2007
32
Descargar