본문 바로가기
Knowledge

[JVM] Java 메모리 관리

by VENUSIM 2024. 12. 27.

 

코드 레벨

  • 불변 객체
    참조 상태가 변경되지 않기 때문에, GC가 객체의 참조를 수시로 확인할 필요가 줄어듬
  • 객체 재사용 고려
  • StreamAPI 이용 (무조건 X, 성능의 이점을 가져올 수 있는 경우에 적용 가능해 보임)
    Lazy Evaluation과 파이프라인 구조 덕분에 중간 연산들은 실제 데이터를 처리하지 않고, 최종 연산이 호출될 때에만 데이터를 처리
  • I/O, 소켓, 쓰레드 등 사용 후 닫았는지 전반적인 확인 (GC가 회수 하지 못함)
    예시) Contents 서버 > outputstream을 사용하고 닫지 않음
  • static 변수 검토 (StackOverflow)
    static 변수는 GC에 의해 회수 되지 않아 사이즈가 큰 객체를 참조가 진행되면서 메모리 누수 가능성
  • 내부 클래스 검토
    생명 주기를 가지거나 이벤트 리스너, 스레드와 같이 비동기적으로 동작하는 경우, 외부 클래스의 인스턴스가 더 이상 필요하지 않더라도 내부 클래스가 계속 존재
    -> 외부 클래스의 인스턴스가 메모리에서 해제되지 않아서 메모리 누수 가능성
  • 약한 참조
    네이버
    https://d2.naver.com/helloworld/329631
    스터디
    https://be-study-record.tistory.com/40
 

아이템 7 다 쓴 객체 참조를 해제하라

객체 참조 해제란 메서드 내에서 사용할 객체를 인스턴스화 하여 로컬 변수에 할당하여 참조하고 사용 후 더 이상 사용하지 않는다고 명시적 null처리로 참조 관계를 끊어주거나 해당 메서드가

be-study-record.tistory.com

https://be-study-record.tistory.com/52

 

Java의 참조 유형

Java의 참조 유형 Java에는 다양한 참조 유형이 있는데 참조 유형에 따라 가비지 컬렉터의 실행 대상 여부 및 시점이 달라진다. Strong Reference (강한 참조) 자바의 기본 참조 유형이다. Class class = new C

be-study-record.tistory.com

 

 

 

class Data {
    private int[] array = new int[3000];
}

class ReferenceTest {

    List<WeakReference<Data>> weakRefs = new LinkedList<>();
    List<SoftReference<Data>> softRefs = new LinkedList<>();
    List<Data> strongRefs = new LinkedList<>();
    
    // out of memory 발생 X
    void weakReferenceTest() {
        try {
            while (true) {
                weakRefs.add(new WeakReference<>(new Data()));
            }
        } catch (OutOfMemoryError outOfMemoryError) { 
            System.out.println("out of memory!");
        }
    }
    // out of memory 발생 X
    void softReferenceTest() {
        try {
            while (true) {
                softRefs.add(new SoftReference<>(new Data()));
            }
        } catch (OutOfMemoryError outOfMemoryError) {
            System.out.println("out of memory!");
        }
    }

    // Strong일 경우 out of memory 발생
    void strongReferenceTest() {
        try {
            while (true) {
                strongRefs.add(new Data());
            }
        } catch (OutOfMemoryError outOfMemoryError) {
            System.out.println("out of memory!");
        }
    }


    static void main(String[] args) {
        System.out.println("실행");

        ReferenceTest test = new ReferenceTest();
        test.weakReferenceTest();
//        test.softReferenceTest();
//        test.strongReferenceTest();

        System.out.println("종료");
    }
}

 

  • JVM
    • MaxTenuringThreshold 수치 조절
      minor gc가 일어날 때 age bit가 증가하고 설정 수치를 넘기 전까지 survivor영역에 남아 있는데, 수치가 높아 계속 남아 있게 되면 결국 가득 차 누수 발생

      반대로 설정 수치가 낮으면 계속해서 tenured 영역으로 넘어가고 Major GC를 대기하는데 Major GC가 일어나기 전에 tenured영역이 가득 차 누수가 발생

      major gc 도중에는 stw(stop the world) 발생 → 모든 애플리케이션 스레드 일시 정지

    • ZGC (STW 개선… 좀 더 알아봐야겠다)
      -XX:+UseZGC
      ZGC의 목적 중 하나는 STW 상태를 10ms 아래로 가져가는 것이다.
      https://d2.naver.com/helloworld/0128759

    • 힙 메모리 사이즈 조절
      최대 : 서버의 가용 메모리의 약 1/4로 설정됨
      최소 : 서버의 가용 메모리의 약 1/64로 설정됨

      예시) esocket 8GB

      기준최대 메모리 사이즈 : 8GB / 4 ≒ 약 2GB
      초기 메모리 사이즈 : 8GB / 64 ≒ 약 127MB
     
    • Heap Dump 와 GC log 설정
      • Heap Dump (IntelliJ에서도 가능하고 Eclipse MAT, VisualVM 등으로 분석)
        > 어떤 객체가 메모리를 차지하고 있는지, 레퍼런스의 구조 등을 분석하는 데 사용
        -XX:+HeapDumpOnOutOfMemoryError :힙 덤프 파일을 생성
        -XX:HeapDumpPath : 힙 덤프가 생성되는 폴더 경로를 지정
        -XX:OnOutOfMemoryError : OOM이 발생할 경우, 수행할 스크립트를 지정

      • GC log
        > GC 이력을 로그 파일
        -Xlog:gc:file=gc-%t.log : 로깅 파일
        -Xlog:gc=info : GC 상세 내역
        -Xlog:gc*:time : GC 발생 시간

 

 

 

 

 

 

 

 

 

'Knowledge' 카테고리의 다른 글

Trie 자료구조 - 14425  (1) 2023.07.19
LinkedList 직접 구현해 보기  (1) 2023.07.11
SQL  (1) 2023.01.09
JDBC  (1) 2023.01.09
Servlet & JSP  (0) 2023.01.09

댓글