컨테이너 환경으로 시스템 이관하는 프로젝트를 진행하면서 주로 자바 애플리케이션을 배포한다. 최근 헤맸던 내용 중 하나를 포스팅해 보려고 한다.

자바 애플리케이션을 war파일로 말아서 컨테이너 환경으로 배포하는 과정에서 log4j 클래스를 못찾는 ClassNotFoudException 에러가 발생했다.

스펙은 아래와 같다

  • JEUS 8
  • OpenJDK 1.8
  • SpringBoot 2.6.7
  • DB2 11.5.6
  • log4jdbc-log4j2-jdbc4.1-1.16.jar
  • 빌드 도구 maven

ClassNotFoudException 에러는 말그대로 클래스를 찾을 수 없다는건데, 진짜 클래스패스에 라이브러리 파일이 없거나 잘못된 클래스패스가 지정되어 있는 그런~그런 에러다

하지만 여기서 간과한 점이 있다.

  • WAS는 JEUS를 사용한다는 점!!! (애플리케이션 war 파일)

JEUS는 클래스패스를 사용하지 않고 자체적으로 클래스로더가 있다고 한다
클래스로더는 컴파일 시점이 아닌 런타임 시점에 클래스를 로딩할 수 있게 해 준다.
일반적으로 Java 클래스로더는 상위로부터 Bootstrap > Extensions > Application 순서대로 올라간다고 한다.

  • Bootstrap : JAVA_HOME/jre/lib/rt.jar
  • Extensions : JAVA_HOME/lib/ext/*.jar
  • Applicaion : CLASSPATH

하지만 JEUS인 경우에는 다르다
system > application > datasource 순서대로 찾아 가는데 웹애플리케이션에 있는 라이브러리 패스를 지정해 주려면 web.xml에서 별도 설정이 필요하다

  • system : JEUS_HOME/lib/system
    JEUS 자체에서 사용하는 라이브러리 위치
  • application : JEUS_HOME/lib/application
    사용자 application에서 사용하는 라이브러리 위치. JEUS 전체 컨테이너에 공유
  • datasource : JEUS_HOME/lib/datasource
    datasource 생성에 필요한 라이브러리

jdbc driver를 사용하려면 드라이버 클래스가 웹애플리케이션 클래스패스(WEB-INF/INF)말고 JEUS_HOME/lib/datasource에 위치해야 JEUS 클래스로더가 찾아갈 수 있다

💡 참고로 maven은 외부 repository에서 pom.xml에 정의된 대로 라이브러리를 다운로드 받을 수 있다. 그럼 WEB-INF/lib에 저장되는데 이는 웹애플리케이션이 사용하는 클래스 파일 경로이다.

참고 ) JEUS Class Loader
참고 ) JVM에 관하여 - Part 2, ClassLoader

Leave a comment