본문 바로가기
프로그램 개발(분석, 설계, 코딩, 배포)/2.2.1 java

자바에서 사용 중인 메모리 체크

by 3604 2025. 6. 30.
728x90
 

이슈

고객사에서 메모리 누수 이슈가 발생했다. 자바 소스가 잘못된 것인지, GC가 잘못 수행된 것인지, 아니면 모듈의 문제(=타 부서가 해결해야 하는 일)인지 명확히 하기 위해서 어디에서 메모리 누수가 발생하고 있는지 확인해야 했다.

프로젝트는 C언어로 된 모듈과 요청에 따라 적절한 모듈을 호출하는 자바 소스로 이루어져 있다.

이 때 Metaspace는 JVM에서 따로 설정해주지 않으면 필요한만큼 계속 메모리를 추가로 차지하기 때문에 이곳에서 메모리 누수가 발생했을 수도 있겠다고 생각했다.

해결

Metaspace에 저장되는 데이터

  1. Garbage Collection
  2. 자바 객체는 새로 생성되면 Eden영역에 자리잡고, Eden 영역이 다 차면 살아남은 객체는 Survivor로 이동하게 된다. Survivor 영역이 다 차면 Old영역으로, Old 영역이 다 차면 Metaspace로 이동한다.
  3. 메타데이터
  4. 여기에서 저장되는 메타데이터는 클래스에 대한 정보들이다. 자바 런타임의 클래스 상태들, 메소드에서 쓰이는 데이터(예외 테이블, 바이트 코드, 메소드 정보 등), 상수 풀, 어노테이션 등이 저장된다.

JVM 설정

우선 자바 코드에서 발생하는 메모리를 제한하기 위해 톰캣의 bin/setenv.sh 파일에 다음 설정을 추가했다.

  1. 초기 Metaspace 크기
  2. CATALINA_OPTS="${CATALINA_OPTS} -XX:MetaspaceSize=512m”
  3. 최대 Metaspace 크기
  4. CATALINA_OPTS="${CATALINA_OPTS} -XX:MaxMetaspaceSize=512m"
  5. 힙 메모리 제한: 이 값을 설정하지 않을 경우 Xmx로 제한한 Heap 메모리만큼 Native Memory 영역을 추가로 사용할 수 있다고 한다.
  6. CATALINA_OPTS="${CATALINA_OPTS} -XX:MaxDirectMemorySize=512m"
  7. Native Memory 추적: 자바 코드에서 Native Memory를 얼마나 사용하는지 확인하는, jcmd라는 명령어가 있다. jcmd를 사용하기 위해서 이 설정이 필요하다.
  8. CATALINA_OPTS="${CATALINA_OPTS} -XX:NativeMemoryTracking=detail”

Xmx를 1024m로 설정해두었기 때문에 1.5기가 이상 사용된다면 모듈의 문제일 것이다.

확인

1시간 동안 의심 모듈을 사용하는 요청을 반복해서 보내보았다. 요청이 너무 많이 몰려 문제가 생길 경우를 대비해 요청 전후로 1초씩 쉬어주었다. 요청이 어느 정도 쌓인 뒤 다음 명령어를 통해 메모리 상태를 확인했다.

  1. do pmap -x 'pgrep java' | tail -1
  2. 자바 프로세스에서 실제로 메모리를 얼마나 사용하고 있는지 확인하기 위해
  3. jcmd 'pgrep java' VM.native_memory summary
  4. 자바에서 할당한 메모리를 확인하기 위해

JVM에서는 1.1기가를 사용하고 있는데 자바 프로세스는 2.6기가를 사용하고 있다. 따라서 모듈에서 메모리 누수 이슈가 발생하고 있다는 것을 확인할 수 있었다.

참고

 

출처: https://velog.io/@qoskdud0928/%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9-%EC%A4%91%EC%9D%B8-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%B2%B4%ED%81%AC

 

728x90