원문 : http://www.vogella.com/articles/EclipseDebugging/article.html 이글은 이클립스 4.2인 Juno를 기준으로 작성되었다.

1. 개요#

1.1. 디버깅이 뭔가?#

디버깅은 실행중에 소스코드와 할당된 변수값등을 보면서 프로그램을 쌍방향으로 실행하게 해준다. 소스코드에서 브레이드포인트(breakpoint)를 통해 프로그램 실행을 중지하도록 명시한다. 필드를 읽거나 변경할때만 실행을 중지하려면 와치포인트(watchpoint)를 명시한다. 브레이크포인트와 와치포인트는 애플리케이션 중지지점으로 요악될수 수 있다. 프로그램이 중지되면 변수를 살펴보거나 값을 변경하는 등의 작업이 가능하다.

1.2. 이클립스에서 디버깅 지원#

이클립스는 디버깅 모드에서 자바 애플리케이션을 시작할 수 있다. 이클립스는 특별히 디버그를 위한 UI인 디버그 퍼스펙티브(Debug perspective)를 가지고 있다. 이 퍼스펙티브에서 프로그램의 실행흐름과 변수의 상태를 살펴볼수 있다.

2. 전제조건#

이 글에서는 독자가 간단한 자바 프로그램을 개발하는 방법을 알고 있다고 가정한다. 그래서 이 글은 이클립스에서 자바 애플리케이션을 디버그하는 방법에만 집중할것이다. 이클립스의 설치및 사용법은 이클립스 자바 IDE튜토리얼에서 볼수 있다.

3. 이클립스에서 디버깅#

3.1. 브레이크포인트 셋팅#

소스코드에서 브레이크포인트를 셋팅하기 위해서는 소스코드 편집기의 왼쪽에 있는 작은 빈공간에 마우스 우측버튼을 클릭하고 Toggle Breakpoint 메뉴를 선택하자. 이 위치에서 더블클릭을 해도 동일하게 브레이크포인트가 셋팅된다.

예를들어 아래의 스크린샷은 Counter counter = new Counter(); 에 브레이크포인트를 셋팅했다.

3.2. 디버거 시작#

애플리케이션을 디버그하기 위해, 실행할 자바파일을 선택하고 마우스 우측버튼을 클릭 후 Debug As → Java Application 메뉴를 선택하자.

마우스 우측버튼을 사용해서 띄운 메뉴에서 애플리케이션을 한번 실행한 뒤에 이클립스 툴바에서 Debug버튼을 사용해서 동일하게 다시 실행할 수 있다.

브레이크포인트가 없다면 프로그램은 일반적인 형태로 실행이 될 것이다. 프로그램을 디버그하기 위해 브레이크포인트를 정의할 필요가 있다. 디버거를 시작한다면 이클립스는 중지지점에 도달했을때 디버그 퍼스펙티브로 전환할지를 물어본다. 다이얼로드창에서는 Yes를 선택하자.

그뒤에 이클립스는 다음의 스크린샷과 유사한 디버그 퍼스펙티브를 연다.

3.3. 프로그램 실행 제어#

이클립스는 디버깅중인 프로그램의 실행을 제어하도록 툴바에서 버튼을 제공한다. 대개 실행을 제어하기 위해 관련된 키를 사용하는데 더 쉽다. 코드를 단계별로 이동하기 위해 F5, F6, F7 그리고 F8 키를 사용할 수 있다. 각 키별 기능은 다음 표에서 설명하고 있다.

표 1. 디버깅 키 바인딩

설명
F5 선택된 라인의 코드를 실행하고 프로그램에서 다음 라인으로 이동한다, 선택된 라인이 메서드 호출이라면 디버거는 관련코드로 바로 이동한다.
F6 F6은 호출을 단계별로 진행한다. 디버거에서 메서드 안으로 들어가지는 않고 메서드를 호출한다.
F7 F7은 현재 실행된 메서드를 호출한 곳으로 이동한다. 현재 메서드를 실행하고 이 메서드를 호출한 곳으로 이동하는 것으로 끝난다.
F8 F8은 다음의 브레이크포인트나 와치포인트에 도달할때까지 이클립스 디버거에게 프로그램을 계속 실행하도록 한다.

다음의 그림은 버튼과 관련된 단축키를 보여준다.

콜스택(call stack)은 현재 실행중인 프로그램의 일부와 어떤 관계인지를 보여준다. 현재의 스택은 Debug뷰에서 볼수 있다.

3.4. Breakpoints 뷰와 브레이크포인트 비활성화#

Breakpoints 뷰는 중지지점을 삭제하고 비활성화하거나 프로퍼티를 변경하는 것이 가능하다. 브레이크포인트를 비활성화하기 위해서 Breakpoints뷰에서 관련체크박스를 제거하자. 삭제하기 위해 뷰툴바에서 관련된 버튼을 사용할수도 있다. 이 옵션은 다음의 스크린샷에서 보여주고 있다.

브레이크포인트를 모두 비활성화하고 싶다면 Skip all breakpoints 버튼을 누르면 된다. 다시 누르면 모든 브레이크포인트가 다시 활성화된다. 이 버튼은 다음의 스크린샷에서 하이라이트되어있다.

3.5. 디버거에서 변수 살펴보기#

Variables뷰는 현재 실행중인 스택에서 필드들과 로컬변수들을 보여준다. 이 뷰에서 변수들을 보기 위해서는 디버거를 실행할 필요가 있다.

정적 변수들을 보기 위해서는 드랍다운 형식의 메뉴를 사용하자.

Variables뷰의 드랍다운 메뉴를 사용해서 표시된 칼럼을 변경할 수 있다. 예를들면 각각의 변수 선언에서 실제 타입을 볼수 있다. 실제 타입을 보기 위해서는 Layout → Select Columns... → Type 순서로 메뉴를 선택하자.

3.6. 디버거에서 변수 할당 변경#

Variables뷰는 변수에 할당된 값을 변경할수 있게 해준다. 다음 스크린샷에서 그 방법을 설명하고 있다.

3.7. 세부적인 포매터를 사용해서 변수들의 표기를 제어#

기본적으로 Variables뷰는 변수의 값을 표시하기 위해 toString() 메서드를 사용한다. 변수값을 표시하는 방법을 정의하기 위해 자바코드를 사용해서 세부적인 포매터를 정의할 수 있다. 예를들면 Counter클래스에서 toString()메서드는 de.vogella.combug.first.Counter@587c94 처럼 의미가 모호한 정보를 보여준다. 그 값을 좀더 읽기편하도록 하기 위해 값을 출력한 변수를 선택하고 마우스 우측버튼을 클릭 후 컨텍스트 메뉴에서 New Detail Formater entry 를 선택하자.

나중에는 결과를 출력하기 위해 클래스의 메서드를 사용할 수도 있다. 여기서는 이 클래스의 메서드중 getResult() 를 사용했다. 이 설정방법은 다음의 스크린샷에서 설명하고 있다.

4. 고급 디버깅 방법#

여기서 다루는 내용은 디버깅을 할때 사용하는 좀더 다양한 옵션을 보여준다.

4.1. 브레이크포인트 프로퍼티#

브레이크포인트를 셋팅한 후 마우스 우측버튼을 클릭해서 Breakpoint Properties 메뉴를 선택하는 것으로 브레이크포인트의 프로퍼티를 선택할 수 있다. 브레이크포인트 프로퍼티를 사용해서 브레이크포인트가 동작하는 상황을 제한할 수 있다. 브레이크포인트 지점을 지나는 횟수인 Hit Count프로퍼티가 12번 이상일 경우에만 브레이크포인트에서 멈추도록 명시할 수 있다. 조건을 추가할수도 있다. 프로그램은 브레이크포인트에서 멈추지만 조건을 추가하면 해당 조건이 만족할때만 브레이크포인트에서 멈춘다. 프로그램이 매번 해당지점에서 도달하는 것처럼 추가로 로그을 출력하고자 할때도 사용할 수 있다. 다음의 스크린샷은 이 셋팅을 설명한다.

4.2. 와치포인트#

와치포인트는 필드에만 적용되는 브레이크포인트들이다. 디버거는 필드를 읽게되거나 변경될때마다 멈출것이다. 브레이크포인트처럼 편집기에서 필드선언부의 좌측영역을 더블클릭하는 방법으로 와치포인트를 셋팅할 수 있다. 필드를 읽을때나 변경할때 멈추도록 아치포인트의 프로퍼티를 셋팅할 수 있다.

4.3. 예외를 위한 브레이크포인트#

자바소스에서 예외가 던져질때 자동으로 해당 예외에 브레이크포인트가 지정되도록 셋팅할 수 있다. 예외 브레이크포인트를 정의하기 위해 Breakpoints뷰툴바에서 Add Java Exception Breakpoint버튼 아이콘을 클릭하자.

디버거가 예외를 잡거나 잡지못하는 예외이더라도 설정할 수 있다.

4.4. 메서드 브레이크포인트#

편집기에서 메서드 헤더부분의 좌측영역을 더블클릭해서 메서드 브레이크포인트를 정의할 수 있다. 메서드를 들어가거나 나가기직전 프로그램을 멈추고자 한다면 설정할 수 있다.

4.5. 로딩 클래스를 위한 브레이크포인트#

클래스 로드 브레이크포인트는 크래스가 로드되는 시점에 멈춘다. 클래스 로드 브레이크포인트를 셋팅하기 위해 Outline뷰에서 클래스를 선택하고 마우스 우측버튼을 클릭 후 Toggle Class Load Breakpoint옵션을 선택하자.

다른 방법으로는 자바 편집기의 클래스 선언옆의 왼쪽선안에서 더블클릭해도 된다.

4.6. 스텝(Step) 필터#

디버깅시 건너띌 대상 패키지를 정의할 수 있다. 테스트를 위한 프레임워크는 사용하지만 디버깅 단계에서 테스트 프레임워크 클래스로는 들어가고 싶지 않을때 유용하다. 이러한 패키지는 Window → Preferences → Java → Debug → Step Filtering 메뉴를 사용해서 설정할 수 있다.

4.7. 히트 카운트(Hit Count)#

모든 브레이크포인트는 히트 카운트 프로퍼티를 명시할 수 있다. 히트 카운트에 정의한 숫자만큼 도달했을때 애플리케이션이 멈춘다.

4.8. Drop to frame#

Drop to frame은 전반적으로 다시 봐야할듯

이클립스는 디버깅을 하는 동안 호출스택의 단계(level)를 선택할 수 있게 해준다. 그리고 특정시점에 JVM을 재시작하도록 해준다. 프로그램의 일부를 리턴할 수 있게 해준다. 변수는 이미 코드가 실행되어 변경된체로 유지되는것을 알아야 한다. 이 기능을 사용하기 위해 스택에서 대상을 선택하고 Debug뷰의 툴바에서 Drop to Frame버튼을 누르다.

주의 : 필드와 외부 데이터는 리셋을 하더라도 영향을 받지 않는다. 예를들어 데이터베이스에 데이터를 넣으면 해당 데이터는 데이터베이스에 삭제되지 않고 그대로 존재하게 된다.

다음의 스크린샷은 이러한 리셋을 설명한다. for 루프를 재시작한다면 필드결과는 초기값으로 셋팅되지 않는다. 그러므로 앞서 실행한 결과를 리셋하지 않은것처럼 루프도 실행되지 않는다.

5. 연습 : 디버깅을 위한 프로젝트 생성#

5.1. 프로젝트 생성#

디버깅을 연습하기 위해 de.vogella.combug.first라고 불리는 새로운 자바 프로젝트를 생성하자. 그리고나서 de.vogella.combug.first 패키지를 생성하고 다음의 클래스를 만들자.
package de.vogella.combug.first;

public class Counter {
  private int result = 0;

  public int getResult() {
    return result;
  }

  public void count() {
    for (int i = 0; i < 100; i++) {
      result += i + 1;
    }
  }
} 
package de.vogella.combug.first;

public class Main {
  
/**
   * @param args
   */

  public static void main(String[] args) {
    Counter counter = new Counter();
    counter.count();
    System.out.println("We have counted " 
        + counter.getResult());
  }
} 

5.2. 디버깅#

Counter클래스에 브레이크포인트를 지정하자. 프로그램과 count메서드의 실행을 디버그하자. getResult() 메서드를 사용해서 Counter를 위한 세부적인 포매터를 정의하자. 프로그램을 다시 디버그하고 새로운 포매터가 사용되는지 확인하자. 브레이크포인트를 삭제하고 클래스 로딩을 위한 브레이크포인트를 추가하자. 프로그램을 다시 디버깅하고 클래스 로딩시 디버거가 멈추는지 확인하자.

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
png
breakpointview10.png 38.8 kB 1 27-Mar-2013 11:40 DongGukLee
gif
classloadbreakpoint.gif 45.3 kB 1 27-Mar-2013 11:41 DongGukLee
png
debug10.png 47.2 kB 1 27-Mar-2013 11:41 DongGukLee
png
debug20.png 54.3 kB 1 27-Mar-2013 11:41 DongGukLee
png
debugstart08.png 27.9 kB 1 27-Mar-2013 11:41 DongGukLee
gif
debugstart10.gif 20.3 kB 1 27-Mar-2013 11:41 DongGukLee
gif
debugstart20.gif 39.1 kB 1 27-Mar-2013 11:41 DongGukLee
gif
debugstart30.gif 3.2 kB 1 27-Mar-2013 11:41 DongGukLee
png
debugtoolbar10.png 11.4 kB 1 27-Mar-2013 11:41 DongGukLee
png
droptoframe10.png 38.9 kB 1 27-Mar-2013 11:41 DongGukLee
gif
exception10.gif 5.7 kB 1 27-Mar-2013 11:41 DongGukLee
gif
methodbreakpoint10.gif 20.8 kB 1 27-Mar-2013 11:41 DongGukLee
gif
setbreakpoint10.gif 10.7 kB 2 27-Mar-2013 11:41 DongGukLee
png
setbreakpoint12.png 18.4 kB 1 27-Mar-2013 11:41 DongGukLee
gif
skipbreakpoints10.gif 6.3 kB 1 27-Mar-2013 11:41 DongGukLee
gif
stack10.gif 5.8 kB 1 27-Mar-2013 11:41 DongGukLee
gif
variables10.gif 4.3 kB 1 27-Mar-2013 11:41 DongGukLee
gif
variables20.gif 9.9 kB 1 27-Mar-2013 11:41 DongGukLee
gif
variables30.gif 5.2 kB 1 27-Mar-2013 11:42 DongGukLee
gif
variables40.gif 8.9 kB 1 27-Mar-2013 11:42 DongGukLee
gif
variables50.gif 10.5 kB 1 27-Mar-2013 11:42 DongGukLee
png
variablesview_change10.png 14.4 kB 1 27-Mar-2013 11:42 DongGukLee
gif
watchpoint10.gif 14.0 kB 1 27-Mar-2013 11:42 DongGukLee
« This page (revision-19) was last changed on 28-Mar-2013 18:10 by DongGukLee