>  기사  >  Java  >  GraalVM 네이티브 이미지의 메모리 관리

GraalVM 네이티브 이미지의 메모리 관리

WBOY
WBOY원래의
2024-09-03 13:45:49792검색

메모리 관리는 애플리케이션에서 메모리를 효과적으로 할당, 활용 및 해제하는 작업을 담당하는 컴퓨터 소프트웨어 개발의 중요한 구성 요소입니다. 그 중요성은 소프트웨어 성능을 향상시키고 시스템 안정성을 보장하는 데 있습니다.

쓰레기 수거

가비지 수집(GC)은 Java 및 Go와 같은 최신 프로그래밍 언어에서 중추적인 역할을 합니다. 사용되지 않는 메모리를 자동으로 감지하고 재활용하므로 개발자가 메모리를 수동으로 관리할 필요성이 줄어듭니다. GC의 개념은 원래 1950년대 후반 LISP 프로그래밍 언어에서 등장하여 자동화된 메모리 관리가 도입되었습니다.

자동화된 메모리 관리의 주요 장점은 다음과 같습니다.

  • 메모리 누수 방지 및 효율적인 메모리 활용
  • 개발 프로세스가 단순화되고 프로그램 안정성이 향상되었습니다.

메모리 속 '쓰레기'의 성격을 이해하고 재생 가능한 공간을 식별하는 것이 필수적입니다. 다음 장에서는 가비지 수집의 기본 원칙을 살펴보는 것부터 시작하겠습니다.

참조 계산 알고리즘 [George E. Collins 1966]

참조 카운팅 알고리즘은 참조 카운트를 추적하기 위해 개체 헤더에 필드를 할당합니다. 이 개수는 새로운 참조가 있을 때마다 증가하고 참조가 제거되면 감소합니다. 개수가 0에 도달하면 해당 개체는 가비지 수집 대상이 됩니다.

다음 코드를 고려하세요.

먼저 d에서 참조하는 데모 값을 사용하여 문자열을 만듭니다(그림 1).

String d = new String("demo");

Memory Management in GraalVM Native Image

그림 1 – 문자열 생성 후

그런 다음 d를 null로 설정합니다. 데모의 참조 횟수는 0입니다. Reference Counting 알고리즘에서는 데모용 메모리를 회수하게 됩니다(그림 2).

d =null; // Reference count of 'demo' becomes zero, prompting garbage collection.

Memory Management in GraalVM Native Image

그림 2 – 참조가 무효화된 경우

참조 카운팅 알고리즘은 프로그램 실행 중에 작동하여 가비지 수집을 위해 프로그램을 일시적으로 중단시키는 Stop-The-World 이벤트를 방지합니다. 그러나 가장 큰 단점은 순환 참조를 처리할 수 없다는 점입니다(그림 3).

예:

public class CircularReferenceDemo {

  public CircularReferenceDemo reference;
  private String name;

  public CircularReferenceDemo(String name) {
    this.name = name;
  }

  public void setReference(CircularReferenceDemo ref) {
    this.reference = ref;
  }

  public static void main(String[] args) {
    CircularReferenceDemo objA = new CircularReferenceDemo("Ref_A");
    CircularReferenceDemo objB = new CircularReferenceDemo("Ref_B");

    objA.setReference(objB);
    objB.setReference(objA);

    objA = null;
    objB = null;
  }
}

여기서는 외부 참조를 무효화함에도 불구하고 objA와 objB 간의 상호 참조로 인해 가비지 수집이 방지됩니다.

Memory Management in GraalVM Native Image

그림 3 – 순환 참조

두 개체 모두 더 이상 액세스할 수 없음을 알 수 있습니다. 그러나 이들은 서로 참조되므로 참조 횟수가 0이 될 수 없습니다. 결과적으로 GC 수집기는 참조 계산 알고리즘을 사용하여 가비지 수집하라는 알림을 받지 않습니다.

이 알고리즘은 std::shared_ptr을 사용하여 C++에서 실제로 구현됩니다. 동적으로 할당된 객체의 수명주기를 관리하도록 설계된 std::shared_ptr은 객체에 대한 포인터가 생성되거나 소멸될 때 참조 카운트의 증가 및 감소를 자동화합니다. 이 스마트 포인터는 C++ 표준 라이브러리의 일부로, 수동 메모리 처리와 관련된 위험을 크게 줄이는 강력한 메모리 관리 기능을 제공합니다. std::shared_ptr이 복사될 때마다 관리 개체의 내부 참조 수가 증가하여 새 참조를 반영합니다. 반대로, std::shared_ptr이 소멸되거나, 범위를 벗어나거나, 다른 객체에 재할당되면 참조 횟수가 감소합니다. 할당된 메모리는 자동으로 회수되고 참조 횟수가 0에 도달하면 객체가 파괴됩니다.
불필요하게 할당된 객체가 없도록 하여 메모리 누수를 효과적으로 방지합니다.

도달가능성 분석 알고리즘 [1978]

접근성 분석 알고리즘은 GC 루트에서 시작하여 객체 그래프를 통과합니다. 해당 루트에서 접근할 수 없는 객체는 복구 불가능한 것으로 간주하여 수집 대상이 됩니다.

아래 이미지와 같이 파란색 원 안의 물체는 살려두어야 하고, 회색 원 안의 물체는 재활용이 가능합니다(그림 4).

Memory Management in GraalVM Native Image

그림 4 – 메모리 누수

이 방법은 참조 카운팅 알고리즘에 내재된 순환 참조 문제를 효과적으로 해결합니다. GC 루트에서 접근할 수 없는 객체는 수집용으로 분류됩니다.

일반적으로 GC 루트로 간주되는 Java 개체는 다음과 같습니다.

  • 현재 메소드 범위 내의 지역 변수
  • 활성 Java 스레드.
  • 클래스의 정적 필드
  • 네이티브 코드의 JNI 참조

GraalVM 네이티브 이미지 개요

GraalVM은 Java 애플리케이션을 GraalVM 네이티브 이미지라는 독립 실행형 실행 바이너리로 변환하는 AOT(Ahead-of-Time) 컴파일러를 제공합니다. Oracle Labs에서 개발한 이 바이너리
애플리케이션과 라이브러리 클래스, 그리고 GC와 같은 런타임 구성요소를 캡슐화하여 JRE(Java Runtime Environment) 없이도 작업이 가능합니다.

이 프로세스에는 도달 가능한 구성 요소를 결정하기 위한 정적 분석, 실행된 블록을 통한 초기화, 후속 기계 코드 번역을 위한 애플리케이션 상태의 스냅샷 생성을 통한 마무리 작업이 포함됩니다.

Substrate VM의 기본 사항

Substrate VM은 Oracle Labs에서 조정하는 GraalVM 제품군의 핵심 부분입니다. 이는 AOT(Ahead-of-Time) 컴파일을 지원할 뿐만 아니라 JavaScript, Python, Ruby와 같은 Java 이외의 언어와 C 및 C++와 같은 기본 언어의 실행도 용이하게 하는 향상된 JVM입니다. 기본적으로 Substrate VM은 GraalVM이 Java 애플리케이션을 독립 실행형 기본 바이너리로 컴파일할 수 있도록 하는 정교한 프레임워크 역할을 합니다. 이러한 바이너리는 실행을 위해 기존 JVM(Java Virtual Machine)에 의존하지 않으므로 배포가 간소화되고
운영 프로세스.

Substrate VM의 주요 기능 중 하나는 짧은 대기 시간과 최소 메모리 공간이 필요한 애플리케이션에 맞게 미세 조정된 특수 가비지 수집기입니다. 이 가비지 컬렉터는 표준 JVM에서 실행되는 기존 Java 애플리케이션과 상당히 다른 고유한 메모리 레이아웃 및 네이티브 이미지와 구별되는 운영 모델을 처리하는 데 능숙합니다. Substrate VM 기본 이미지에 JIT(Just-In-Time) 컴파일러가 없다는 것은 실행 파일의 전체 크기를 최소화하는 데 도움이 되는 전략적 선택입니다. 크기와 복잡성이 상당한 JIT 컴파일러 및 관련 메타데이터를 포함할 필요가 없기 때문입니다.

게다가 GraalVM은 Java를 사용하여 개발되지만 이로 인해 특히 기본 메모리 액세스 측면에서 특정 제약이 발생합니다. 이러한 제한은 주로 보안 문제와 다양한 플랫폼 간의 호환성을 유지해야 하는 필요성 때문에 발생합니다. 그러나 최적의 가비지 수집 작업을 위해서는 기본 메모리에 액세스하는 것이 필수적입니다. 이 문제를 해결하기 위해 Substrate VM은 기본 메모리와의 안전하고 효율적인 상호 작용을 촉진하는 특수 인터페이스 제품군을 사용합니다. 이러한 인터페이스는 더 광범위한 GraalVM 아키텍처의 일부이며 Substrate VM이 C와 같은 하위 수준 언어와 유사한 방식으로 메모리를 효과적으로 관리하는 동시에 Java의 안전성과 관리 용이성을 유지하도록 해줍니다.

실제로 이러한 기능을 통해 Substrate VM은 GraalVM으로 컴파일된 애플리케이션의 기능과 효율성을 향상시키는 매우 다양한 도구가 됩니다. 개발자가
더 넓은 범위의 프로그래밍 언어를 활용하고 이를 효율적인 기본 바이너리로 컴파일하는 Substrate VM은 기존 Java 개발 환경으로 달성할 수 있는 것의 한계를 뛰어넘습니다. 이는 고성능, 리소스 소비 감소 및 다양한 언어 지원을 요구하는 현대 소프트웨어 개발 프로젝트에 귀중한 자산입니다.

Substrate VM의 주목할만한 요소는 다음과 같습니다.

  • 원시 메모리 작업을 위한 포인터 인터페이스 포인터 및 단어 크기 값을 처리하기 위한 WordBase 인터페이스 WordBase와 같은 인터페이스를 통해 메모리 액세스가 단순화되었습니다.

  • 힙을 불변 객체가 포함된 사전 초기화된 세그먼트와 동적 객체 할당을 위한 런타임 세그먼트로 나눕니다(그림 5).

Memory Management in GraalVM Native Image

그림 5 – 네이티브 이미지의 메모리 관리

런타임에 Substrate VM의 소위 이미지 힙에는 이미지 빌드 프로세스 중에 생성된 개체가 포함됩니다. 힙의 이 섹션은 실행 가능한 바이너리 데이터 섹션의 데이터로 사전 초기화되어 있으며 애플리케이션 시작 시 쉽게 액세스할 수 있습니다. 이미지 힙에 있는 개체는 불멸의 개체로 간주됩니다. 따라서 이러한 객체 내의 참조는
에 의해 루트 포인터로 처리됩니다. 가비지 컬렉터. 그러나 GC는 루트 포인터에 대한 이미지 힙 부분, 특히 읽기 전용으로 표시되지 않은 부분만 스캔합니다.

빌드 프로세스 중에 읽기 전용으로 지정된 개체는 이미지 힙의 특정 읽기 전용 섹션에 배치됩니다. 이러한 객체는 런타임에 할당된 객체에 대한 참조를 절대 보유하지 않으므로 루트 포인터가 포함되어 있지 않으므로 GC가 검색 중에 이를 우회할 수 있습니다. 마찬가지로 기본 데이터나 기본 유형의 배열로만 구성된 객체에도 루트 포인터가 없습니다. 이 속성은 GC 스캔에서 이러한 객체를 생략할 수 있으므로 가비지 수집 프로세스를 더욱 간소화합니다.

반대로, Java 힙은 런타임 중에 동적으로 생성되는 일반 객체를 보관하도록 지정됩니다. 힙의 이 부분은 더 이상 사용되지 않는 객체가 차지하는 공간을 회수하기 위해 정기적인 가비지 수집을 거칩니다. 노화 메커니즘을 갖춘 세대별 힙으로 구성되어 시간이 지남에 따라 효율적인 메모리 관리가 가능합니다.

사전 초기화된 불멸 이미지 힙과 동적으로 관리되는 Java 힙 간의 이러한 구분을 통해 Substrate VM은 애플리케이션 메모리 요구 사항의 정적 및 동적 측면을 모두 충족하면서 메모리 사용 및 가비지 수집 효율성을 최적화할 수 있습니다.

힙 청크

Substrate VM의 힙 모델에서 메모리는 힙 청크로 알려진 구조로 체계적으로 구성됩니다. 일반적으로 기본 크기가 1024KB인 이러한 청크는 객체 스토리지에만 할당되는 연속적인 가상 메모리 세그먼트를 형성합니다. 이러한 청크의 조직 구조는 꼬리 청크가 가장 최근에 추가된 세그먼트를 나타내는 연결 목록입니다. 이런 모델
효율적인 메모리 할당 및 객체 관리를 용이하게 합니다.

이러한 힙 청크는 정렬된 유형과 정렬되지 않은 유형의 두 가지 유형으로 더 분류됩니다. 정렬된 힙 청크는 여러 개체를 연속적으로 보유할 수 있습니다. 이 정렬을 통해
매핑을 더 쉽게 할 수 있습니다. 객체를 각각의 상위 힙 청크에 추가하여 메모리 관리를 더욱 직관적이고 효율적으로 만듭니다. 개체 승격이 필요한 시나리오(일반적으로 가비지 수집 및
중) 메모리 최적화 - 개체가 상위 힙 청크의 원래 위치에서 지정된 "이전 공간"에 있는 대상 힙 청크로 이동됩니다. 이 마이그레이션은 젊은 개체를 오래된 개체와 분리하여 GC 주기 중 오버헤드를 줄여 가비지 수집 프로세스를 최적화하는 데 도움이 되는 세대별 힙 관리 전략의 일부입니다.

네이티브 이미지의 가비지 수집기

GraalVM 네이티브 이미지는 다양한 요구 사항에 맞는 다양한 GC를 지원합니다.

  • 직렬 GC: 단일 스레드 애플리케이션에 적합한 기본 저용량 수집기입니다.

  • G1 Garbage Collector: 힙 크기가 큰 멀티 스레드 애플리케이션용으로 설계되어 세대 관리의 유연성이 향상되었습니다.

  • Epsilon GC: 할당을 처리하지만 회수가 부족한 최소한의 수집기로서, 전체 힙 활용이 예측 가능한 단기 애플리케이션에 가장 적합합니다.

결론

결론적으로 Substrate VM은 특수 가비지 수집 및 구조화된 힙 관리와 같은 고급 기술을 통합하여 GraalVM 내에서 메모리 관리를 효과적으로 최적화합니다. 힙 청크와 이미지 및 Java 힙을 위한 별도의 메모리 세그먼트를 포함한 이러한 기능은 가비지 수집을 간소화하고 애플리케이션 성능을 향상시킵니다. Substrate VM은 다양한 프로그래밍 언어를 지원하고 이를 효율적인 기본 바이너리로 컴파일하므로 최신 JVM 프레임워크가 기존 경계를 넘어 확장하여 다양한 애플리케이션 환경에서 실행 효율성과 견고성을 향상시킬 수 있는 방법을 보여줍니다. 이러한 접근 방식은 가상 머신 기술 및 애플리케이션 배포의 향후 개발을 위한 높은 표준을 설정합니다.

위 내용은 GraalVM 네이티브 이미지의 메모리 관리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.