Java/오류노트

[Java/오류노트] Solved - Handler dispatch failed: java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager

adjh54 2025. 2. 27. 18:47
728x170
해당 글에서는 Docker 기반의 Could not initialize class sun.awt.X11FontManager 문제에 대한 해결 방법에 대해 작성한 글입니다.


 

 

1) 문제점


💡 문제점

- 엑셀 다운로드 기능을 Apachce POI 라이브러리를 이용하여서 구현하였고 이를 실행하였을때 로컬에서는 정상적으로 다운로드가 되었지만, 해당 코드를 Docker 기반 개발서버로 올렸을 경우 아래와 같은 오류가 발생하였습니다.

- Exception jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManagerjava.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager

- java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager

 

💡 [참고] 사용한 Apache POI Common 라이브러리

https://mvnrepository.com/artifact/org.apache.poi/poi

 

 

💡 [참고] 문제가 발생한 코드 일부 Repository
 

blog-codes/spring-boot-excel-poi at main · adjh54ir/blog-codes

Contributor9 티스토리 블로그 내에서 활용한 내용들을 담은 레포지토리입니다. Contribute to adjh54ir/blog-codes development by creating an account on GitHub.

github.com

 

 

3) 해결방법


💡 해결방법

- 해당 오류에서는 Apache POI를 사용하여 엑셀 파일을 생성하는 과정에서 ‘X11FontManager’ 클래스를 불러오지 못하는 문제였습니다. 이는 Apache POI는 내부적으로 AWT를 사용하여 엑셀 파일의 폰트나 색상 처리를 위해 AWT 관련 클래스를 호출합니다.
- 해당 클래스의 경우는 GUI 그래픽 사용자 인터페이스를 사용하는데 이용됩니다. 그렇기에 GUI를 사용하지 않는 헤드리스 서버 환경을 설정해야 이를 이용할 수 있습니다.
 

Using Headless Mode in the Java SE Platform

This article explains how to use the headless mode capabilities of the Java Platform, Standard Edition (Java SE, formerly referred to as J2SE). Headless mode is a system configuration in which the display device, keyboard, or mouse is lacking. Sounds unexp

www.oracle.com

 

[ 더 알아보기 ]

💡 AWT(Abstract Window Toolkit)


- Java의 GUI(그래픽 사용자 인터페이스) 프로그래밍을 위한 최초의 라이브러리입니다. Java SE 플랫폼의 일부로, 윈도우, 버튼, 텍스트 필드 등과 같은 GUI 컴포넌트를 구현하는 데 사용됩니다.
- Apache POI와 같은 라이브러리가 내부적으로 AWT를 사용하는 경우가 많은데, 특히 엑셀 파일 생성 시 폰트나 색상 처리를 위해 AWT 관련 클래스를 호출합니다.

💡 헤드리스 모드(Headless Mode)

- 그래픽 디스플레이(모니터)가 없는 환경에서 그래픽 기반의 작업을 수행할 수 있게 해주는 기능입니다.
- 서버 환경에서는 일반적으로 GUI가 없기 때문에, AWT나 Swing과 같은 Java의 GUI 컴포넌트를 사용하는 작업을 수행하려면 헤드리스 모드를 활성화해야 합니다.
- 헤드리스 모드가 활성화되면, 시스템은 실제 디스플레이 장치가 없어도 가상의 프레임버퍼를 사용하여 그래픽 작업을 수행합니다. 주로 서버 환경에서 이미지 처리, PDF 생성, 엑셀 파일 생성 등과 같은 작업을 할 때 필요합니다.

 

 

1. 헤드리스 모드 적용


💡 헤드리스 모드 적용

- 해당 헤드리스 모드를 적용하면 GUI가 없는 서버 환경에서도 엑셀 다운로드 같은 기능이 정상적으로 작동할 수 있습니다


- System Properties를 애플리케이션 코드 내에 포함하는 방법과 Docker를 이용하는 경우 Docker 내에 환경 변수를 추가하는 방법입니다. 이 두 방법을 동시에 적용할 필요는 없고 상황에 따라 적용하시면 됩니다.

The Java Headless Mode | Baeldung

 

1.1. System Properties 설정 적용 방법 -1


 💡 System Properties 설정 적용 방법 -1

- 첫 번째 방법으로 xxApplication.java 파일 내에 System.setProperty를 통해서 Java 시스템 속성을 설정하였습니다.
- 해당 속성으로 헤드리스 모드를 활성화하는 값으로 지정하였습니다.
package com.blog.springbootexcelpoi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootExcelPoiApplication {

    public static void main(String[] args) {

        // 애플리케이션 시작 전에 headless 모드 설정
        System.setProperty("java.awt.headless", "true");
        SpringApplication.run(SpringBootExcelPoiApplication.class, args);

    }

}

 

 

1.2. Docker 파일 내에 환경 변수로 적용 방법 -2


💡 Docker 파일 내에 환경 변수로 적용 방법 -2

- 두 번째 방법으로 Docker 파일 내에 환경 변수로 적용하는 방법은 Dockerfile에 Java 애플리케이션을 실행하는 명령어에 직접 JVM 옵션을 추가하는 방식입니다.
- 아래의 예시에서는 ENTRYPOINT 명령어를 사용하여 컨테이너가 시작될 때 실행될 명령어를 지정하였습니다.
FROM openjdk:17-jdk-alpine
// ...
ENTRYPOINT ["java", "-Djava.awt.headless=true", "-jar", "./app.jar"]

 

 

2. Docker 이미지 확인


💡 Docker 이미지 확인

- 위에 내용을 적용하였는데도 수행하지 않았을 때, 특정 글을 착안하여서 Docker 이미지를 변경하는 작업을 수행하였습니다.

- 기존의 openjdk:17-jdk-alpine 버전을 사용하고 있었는데, 경량화 버전이기에 일부 지원을 하지 않는다는 문제점을 파악하였고 openjdk:17-jdk 버전으로 변경하여 최종적으로 해결하였습니다.
# 변경 이전
FROM openjdk:17-jdk-alpine
// ...
ENTRYPOINT ["java", "-Djava.awt.headless=true", "-jar", "./app.jar"] 

# 변경 이후
FROM openjdk:17-jdk
// ...
ENTRYPOINT ["java", "-Djava.awt.headless=true", "-jar", "./app.jar"] 
 

https://hub.docker.com/layers/library/openjdk/17-alpine/images/sha256-a996cdcc040704ec6badaf5fecf1e144c096e00231a29188596c784bcf858d05

 

hub.docker.com

 

https://hub.docker.com/layers/library/openjdk/17-jdk/images/sha256-98f0304b3a3b7c12ce641177a99d1f3be56f532473a528fda38d53d519cafb13?context=explore

 

hub.docker.com

 

3. 추후 개선 포인트


💡 추후 개선 포인트

- alpine 버전을 사용하다가 일반 버전을 사용하는 경우 이미지 크기도 커지며, 비용문제도 발생할 수 있기에 이에 대한 변경을 추후 필요하였습니다.

- 그렇기에 alpine 이미지 버전에 필요한 라이브러리를 추가하는 방법을 생각해보아야 할 것 같습니다.

 

 

 

 

오늘도 감사합니다 😀 

그리드형