태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

티스토리 툴바


"올바른 성장과 따뜻한 나눔"이 있는 넥스트리
어플리케이션에 문제가 있는 경우 문제가 되는 메소드를 누가 호출하지는 궁금할 때가 있다. 특히 운영중 평소에는 잘 돌다가 특정한 경우에 문제가 되는 메소드를 호출하여 장애가 발생하는 경우는 재현하기도 어렵고 추적하기도 매우 어렵다. 이런 경우 기본 Java Debugger인 jdb가 유용하다. (JDK에 기본으로 있다.)




상황1: 잘 돌던 웹 애플리케이션이 종종 죽는다.

물론 JVM 레벨에서 죽는 경우도 가끔있지만 이런 경우 대부분 core dump가 떨어진다. 그런데 dump도 떨어지지 않고 가끔 죽는 경우가 있어 혹시 개발자가 실수로 코드에서 System.exit를 호출하지 않았나 살펴보기로 하자.

- WAS 디버그로 구동하기
먼저 WAS 구동 시 -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n 옵션을 주어 디버깅 모드로 구동한다. 이는 WAS 마다 설정방법이 조금씩 다르니 WAS 구동하는 스크립트를 잘 찾아본다. 여기(http://greatkim91.tistory.com/entry/WAS에서-동작하는-프로그램-원격-디버깅하기) 를 참조한다. 이 경우 8000번 포트로 디버그 접속을 열어놓았다.


- jdb로 접근하기
telent이나 도스창 같은 콘솔에서 다음과 같은 명령으로 jdb로 WAS에 접근한다.

prompt> jdb -connect com.sun.jdi.SocketAttach:port=8000

- monitor 걸기
jdb 안에서 다음 명령을 수행한다.

> stop in java.lang.System.exit
> monitor where

1라인: java.lang.System.exit 메소드에 breakpoint를 건다.
2라인: breakpoint에 걸리면 현재 stack trace를 출력한다.

이렇게 걸어 놓고 두면 언제가 웹애플리케이션이 죽으면 jdb 콘솔안에 다음과 같이 System.exit를 호출할 때의 stack을 남겨놓는다.




상황2: 어디선가 gc를 수행하고 있다.

모 프로젝트에서 별다른 패턴없이 full gc(garbage collection)을 수행하는 경우가 있었다. Java의 gc는 성능에 영향을 크게 미치는데 full gc는 특히 더 하다. 누군가 System.gc()를 호출하는 것은 아닌가 의심하고 디버그를 걸어놓기로 했다.

- 위와 같이 WAS를 디버그 모드로 구동하고 jdb로 접근한다.

- monitor 걸기

> stop in java.lang.System.gc
> monitor where
> monitor cont

1,2라인: 위와 동일하다.
3라인: gc한다고 서비스 멈추면 안되니 breakpoint 걸려 멈춘 (suspend) 쓰레드것들 계속진행(resume)하게 한다.

마찬가지로 서비스 중 gc가 호출되었다면 다음과 같이 gc가 호출되었을때의 stack이 출력되어 있을 것이다.



주의: WAS를 디버그 모드로 띄우면 메모리를 더 차지하는 등 성능에 악영향을 미칩니다. 평소에는 절대 디버그 모드로 띄우지 말고 위와 같이 아주 급한 상황에서 1대 정도만 디버그로 띄워서 문제를 잡아야 합니다.


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 행복한아빠