행복한 아빠

어떤 클래스가 로드되는지 알아내기 본문

문제발생시

어떤 클래스가 로드되는지 알아내기

행복한아빠 2010. 2. 4. 19:35
사용자 삽입 이미지
개발 중 가끔 클래스를 수정해서 올렸는데 계속 적용이 되지 않는 경우가 있습니다. 그래서 계속 수정해서 올리고 변경이 안되어 쓸데없는 시간을 보내곤 합니다.
여기에서는 지금 구동 중인 java 클래스가 어디에서 로드되는지 알아내는 방법을 소개합니다.



사전지식

JVM의 Classloader 구조를 정확히 이해하고 클래스가 어디에서 어떻게 로드되어 구동되는지 알아야 합니다. 일반적으로 JVM의 클래스로더는 계층(hierarchy)구조를 가지고 있으며 각 클래스 로더는 하나의 부모 클래스 로더를 갖습니다. (물론 루트: boot classloader 제외)
다음은 Tomcat의 클래스로더 구조입니다. (WAS 마다 조금씩 다르지만 거의 비슷합니다.)
사용자 삽입 이미지


클래스 로더의 규칙은 다음과 같습니다.
  • 클래스 로더는 동일한 클래스는 한번만 로드합니다.
  • 동일한 이름(패키지 포함)을 가지고 동일한 클래스로더에서 로드된 클래스일 경우만 같은 클래스로 취급합니다. 클래스 이름을 가지더라도 서로 다른 클래스로더에서 로드될 경우 다른 클래스이며 이 경우 같은 클래스가 아니라는 에러를 발생합니다.
    간혹 동일한 클래스(동일 패키지)인데도 클래스가 다르다는 이상한 에러를 만날 경우가 이런 경우입니다.
  • 우선 자신의 클래스로더에서 클래스를 찾고 없으면 부모 클래스로더에서 찾습니다. 즉 클래스를 찾는 순서는 tomcat의 경우 클래스 로드 순서는 다음과 같습니다.
    WebappX -> Shared -> Common -> System -> Bootstrap
예전에 Websphere에서 클래스를 찾는 순서를 반대로 (부모 클래스로더부터) 하는 설정이 있는 것을 보았습니다. 이건 일반적인 것은 아니고 해당 WAS에만 있는 특이한 경우입니다. 아직도 그 설정이 있는지 모르겠습니다. 5년도 더 된 것 같은데...


지금 동작중인 클래스 찾기

클래스를 수정해서 배포했는데 그 클래스가 적용되지 않는 경우 동일한 이름의 클래스가 여러 군데 있을 가능성이 높습니다. 즉 수정된 클래스는 상위 클래스로더에 계속 배포하고 테스트할 때는 다른 곳에(주로 자식클래스 로더) 이전의 클래스가 동작하여 헤매고 삽질하게 되는 경우가 있습니다.
다음 JSP 파일을 이용하여 쉽게 Web app에서 동작 중인 클래스를 찾아낼 수 있습니다.


원래 여러 가지 기능을 넣는라고 여러 유틸리티 클래스가 필요했는데 배포가 쉽도록 JSP안에 구겨넣었습니다.

WAR가 배포되는 위치에 이 jsp를 넣고 접근하면 Class Name을 입력하는 입력박스가 있습니다. 여기에 찾고자 하는 클래스 이름을 넣습니다. (예: oracle.jdbc.driver.OracleDriver)
사용자 삽입 이미지

위 그림이 그 결과입니다. Classloaders 항목에 클래스를 로드한 클래스 로더 정보가 나타납니다. 실제 클래스를 로드한 클래스 로더는 위의 경우 StandardClassLoader이고 그 아래는 그 부모 클래스 로더들입니다.
그리고 File Name을 보시면 실제 어떤 클래스 파일에서 로드했는지 보여줍니다. 위의 경우 oracle-10g_xe.jar 파일 안의 클래스를 로드 했네요.

그외 아래 정보는 WAS에 상관없이 JVM이 기본으로 로드하는 클래스 위치를 알려주는 정보입니다.
  • Boot Classes: JVM이 기본으로 로드하는 클래스들
  • Extension Classes: JVM extension directory에서 로드한 클래스들
  • Application Classes: CLASSPATH에 설정한 클래스들
리소스 찾기

클래스패스 상의 리소스(텍스트파일, 이미지, ...)들을 찾는 방법도 유사합니다.
전형적인 예로 classpath에 걸린 log4j.properties를 아무리 수정해도 적용이 되지 않는 경우가 있습니다. 이 경우 다른 JAR 안이나 다른 위치에 log4j.properties가 있을 확률이 높습니다.
역시 다음 JSP 파일로 로드된 리소스와 동일한 이름의 리소스가 있는 위치들을 알려줍니다.



사용자 삽입 이미지
log4j.properties를 입력하고 엔터를 치며 위와 같이 리소스가 로드된 위치와 동일한 이름의 리소스들이 어디에 있는지 알아낼 수 있다.
리소스 이름은 클래스와 다르게 디렉토리를 "/"로 표현합니다. (예: kr/nextree/bcf/core/sqlmap/sqlmap-config.xml)
소스를 잘 보면 로드된 리소스의 내용을 출력하는 기능도 넣을 수 있겠죠...


정리

위 클래스 찾기와 리소스 찾기는 JSP 파일이 있는 webapp의 클래스로더에서 클래스와 리소스를 검색합니다. 따라서 상위 클래스로더에서 로드된 클래스가 참조하는 클래스에 문제가 생겼을 경우는 클래스로더 구조를 잘 파악하여 다른 방법으로 접근해야 할 수도 있습니다.
그러나 이 정도 방법으로도 대부분의 클래스 찾기와 관련된 문제를 해결할 수 있었습니다.

6 Comments
댓글쓰기 폼