Java/Theory

[Java/Theory]18. Exception Handling

양승길 2016. 5. 31. 12:27

18. Exception Handling

    JVM에서 실행중인 프로그램이 예외가 발생하여 Bytecode에서 처리하는 과정.

    Exception Handling의 목적은 견고한 Application을 만드는 것이다.

    Object 밑에 있는 Throwable Class에서 제공된다.

    Throwable에는 다양한 Exception Class가 있다. 

    (0으로 나눌때, 배열 색인 이탈, wrong casting...)

    

  * 처리 원리

      최초 예외가 발생한 시점을 출발점을 두어 관련된 구문을 추척하면서 Call Stack에 저장한다.

      Call Stack : Stack의 자료구조 형태로서 최초에 발생한 예외시점을 최하위단부터 저장한다.

      Call Stack에서 최상위에 있는 예외에서 catch로 인하여 처리가 되면 끝나겠지만,

      처리가 불가능하면 바로 밑에 있는 예외를 처리한다. 그러한 방식으로 처리가 되지 못하고

      최하위단에 있는 예외 조차 처리하지 못하면 JVM은 예외발생이 된다.

      

      

    -> throws

        예외가 발생한 Method를 호출한 지점으로 예외를 전달하여 처리하는 Keyword

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public void avg(int z) throws ArithmeticException { 
 
    System.out.println("Start Avg");
    // 이곳에서 해결한다. throws는 위임에 불과하고, 시스템에서 해결책을 제공하지 않는다.
 
    avg = sum/z;
    System.out.println("Avg : " + avg);
    System.out.println("End Avg");
 
// end of avg
 
 
 
public static void main(String [] args){
 
    int i = 10;
    int j = 20;
    int k = 0;
 
    ExceptionTest04 et = new ExceptionTest04();
    et.sum(i,j);
 
    try{
        // try - catch 구문이 없다면 아래 Method는 미해결 된채, 프로그램이 종료된다.
        et.avg(k);
    }catch(ArithmeticException e){
 
        // ArithmeticException의 최상위 Class역시 Object 이기 때문에 toString이 생략되어 있다.
        System.out.println(e);
 
        // 이 Method는 
        // 예외가 발생한 곳을 출력해준다.
        // Call Starck : Stack의 자료구조 형태로서 최초에 발생한 시점을 우선순위로 저장한다.
        // 최후에 발생한 예외를 먼저 출력하고
        // 그 역순으로 다른 발생 지점을 보여준다.
        e.printStackTrace();
 
    } // end of try catch
 
    System.out.println("End" );
 
// end of main
 
cs


  * API에서 정의된 예외

      int i = Integer.parseInt("a"); 와 같은 구문에서 예외가 발생된다.

      parseInt를 보면 NumberFormatException이 처리되어 있다.

      이에 따라 stackTrace를 보면 API에 있는 Line number를 출력하면서

      최하단에 사용자가 타이핑한 구문이 출력된다.

      결론은 API에서 정의된 예외에 대한 stackTrace 사용자의 잘못된 타이핑을 알아둬야 한다.


    * Throwable은 Error와 Exception으로 분류된다.


  * Exception의 분류

      -> Unchecked(Arithmetic, NullPointer, ArrayIndexOutOfBound, IllegalArgument)

          Runtime Exception에 있는 모든 Class

          사용자가 Validation Check를 설정 할 수 있기 때문에

          Compiler가 try - catch문을 작성하라는 오류 메세지를 출력하지 않는다.

          (Error Class도 마찬가지)


      -> Checked(IOException)

          Error와 Runtime Exception에 있는 모든 Class를 제외한 예외.

          사용자가 Validation Check를 설정 할 수 없기 때문에

          Compiler가 try - catch문을 작성하라는 오류 메세지를 출력한다.


  * finally System.exit(0), return 

      try에서 예외가 발생되어 그 시점 이후에 처리되지 않을때나,

      catch에서 처리 유무 관계 없이

      시행하는 구문이다.


      ->finally의 필요성

         try, catch에 return이 작성되어 있어도 finally는 수행되나,

         block 밖에 있는 구문은 처리 되지 않는다.

         (System.exit(0)은 프로세스를 죽이는 Method이므로 finally는 수행하지 않는다.)


    * main throws

      main Method에 throws를 선언할 경우

1
2
3
4
5
public static void main(String args[]) throws Exception{
    try{
        throw new Exception();
    }
}
cs

      -> Call Stack구조를 보면 예외는 throw new Exception();만 있고

          처리할 방법이 없기 때문에 throws Exception을 참조하여

          JVM이 예외를 발생시킨다.

          throws Exception를 작성하지 않으면 Compile에러가 발생된다.


  * catch heirachy

      catch문을 작성할 때 가장 먼저 사용될 예외 Class는 가장 하위의 SubClass다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try{
    fileReader = new FileReader(str); 
    fileReader.read(c,0,1024);          
}catch(FileNotFoundException e1){
    System.out.println("e1 : "+e1);
    System.out.println(str+" : File이 없습니다.");
}catch(IOException e2){
    System.out.println("e2 : "+e2);
    System.out.println("read() method에서 Exception 발생");
}catch(Exception e3){
    System.out.println("e3 : "+e3);
    System.out.println("모든 Exception 은 내가 잡느다.");
}finally{
    System.out.println("여기는 fileRead() :: Exception이 발생하던 말던 나는 실행");
}
cs


      허나 Object가 최상위 Class라고 해서 catch문에서 작성하면 오류가 나는데,

      catch문에서는 Throwable에서 사용되는 Class들만 적용이 가능하다.


  * throw

      사용자에 필요에 따라 API에 없는 예외를 작성해야 된다면 throw를 작성하게 된다.

1
2
3
4
5
6
7
8
9
10
public void test(int number) throws FindOddException{
    System.out.println(":: " + this.getClass().getName() + "start.");
 
    if(number % 2 == 0){
        System.out.println(number);
    }else{
        throw new FindOddException("0");
    }
    System.out.println(":: " + this.getClass().getName() + "end.");
// end of test
cs


- 취약점

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class ExTest {
    public static void ex(){
        try{
            System.out.println("ㅎㅎㅎㅎㅎ");
            throw new Exception();
        }catch(Exception e) {
            System.out.println("ㅋㅋㅋㅋㅋ");
        }
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try{
             ex();
        }catch(Exception e){
            System.out.println("ㄴㄴㄴㄴㄴ");
        }finally{
            System.out.println("ㅇㅇㅇㅇㅇ");
        }
        
 
    }
}
 
// 출력 결과
// ㅎㅎㅎㅎㅎ
// ㅋㅋㅋㅋㅋ
// ㅇㅇㅇㅇㅇ
cs