문제

JVM(Java Virtual Machine)이 메모리의 객체를 이동한 적이 있나요? 그렇다면 이동된 객체에 대한 참조 업데이트를 어떻게 처리합니까?

분산 방식으로 객체를 저장하는 아이디어를 탐구하고 있기 때문에 질문합니다(예:여러 서버에 걸쳐), 효율성을 위해 서버 간에 개체를 이동할 수 있는 기능이 필요합니다.개체는 서로에 대한 포인터를 포함할 수 있어야 하며, 원격 서버의 개체에 대한 포인터도 포함할 수 있어야 합니다.이동된 개체에 대한 참조를 업데이트하는 가장 좋은 방법을 생각하려고 합니다.

지금까지 내 두 가지 아이디어는 다음과 같습니다.

  1. 객체의 수명 동안 움직이지 않는 참조 간접 참조를 유지합니다. 객체가 움직이면 업데이트됩니다.하지만 - 이러한 간접 참조는 어떻게 관리됩니까?
  2. 각 개체에 대한 역참조 목록을 유지하여 개체가 이동된 경우 업데이트해야 할 내용을 알 수 있습니다.물론 이로 인해 성능 오버헤드가 발생합니다.

이러한 접근 방식에 대한 피드백과 대안 접근 방식에 대한 제안에 관심이 있습니다.

도움이 되었습니까?

해결책

힙 걷기에 대한 위의 설명을 참조하세요.

다른 GC는 다른 방식으로 수행합니다.

일반적으로 힙을 탐색할 때 수집기를 복사하면 힙의 모든 개체를 탐색하지는 않습니다.오히려 그들은 힙에 있는 LIVE 객체를 탐색합니다.이는 "루트" 개체에서 접근할 수 있으면 해당 개체가 활성 상태라는 의미입니다.

따라서 이 단계에서는 이전 힙에서 새 힙으로 객체를 복사하므로 모든 활성 객체를 터치해야 합니다.라이브 객체의 복사가 완료되면 이전 힙에 남아 있는 모든 객체는 이미 복사된 객체이거나 가비지입니다.이 시점에서 이전 힙을 완전히 삭제할 수 있습니다.

이러한 종류의 수집기의 두 가지 주요 이점은 복사 단계에서 힙을 압축하고 살아있는 객체만 복사한다는 것입니다.이런 종류의 수집기를 사용하면 객체 할당이 문자 그대로 힙 포인터를 증가시키는 것보다 조금 더 저렴하기 때문에 이는 많은 시스템에서 중요합니다.GC가 발생하면 "죽은" 객체는 복사되지 않으므로 수집기의 속도가 느려지지 않습니다.또한 동적 시스템에서는 오래 지속되는 쓰레기보다 작은 임시 쓰레기가 훨씬 더 많은 것으로 나타났습니다.

또한 실시간 개체 그래프를 살펴보면서 GC가 어떻게 모든 개체에 대해 "알고" 복사 중에 수행되는 모든 주소 조정 목적을 위해 이를 추적할 수 있는지 확인할 수 있습니다.

이것은 사소한 문제가 아니기 때문에 GC 역학에 대해 깊이 이야기하는 포럼은 아니지만 이것이 복사 수집기 작동 방식의 기본입니다.

세대 복사 GC는 "오래된" 개체를 다른 힙에 배치하며 이러한 개체는 "새로운" 힙보다 수집되는 빈도가 줄어듭니다.이론상으로는 오래 지속되는 개체가 이전 세대로 승격되고 수집되는 횟수가 점점 줄어들어 전반적인 GC 성능이 향상된다는 것입니다.

다른 팁

(실질적으로) 모든 가비지 수집 시스템은 객체를 더 조밀하게 패킹하고 조각화 문제를 피하기 위해 메모리에서 객체를 이동해야 합니다.

당신이 보고 있는 것은 매우 크고 복잡한 주제입니다.기존 원격 개체 스타일 API에 대해 읽어 보시기 바랍니다..NET 원격 및 더 이전 기술로 돌아가는 것과 같은 코르바

참조를 추적하는 솔루션은 분산 시스템에 존재하는 모든 오류 모드를 처리해야 하므로 복잡해집니다.JVM은 네트워크 스위치 결함으로 인해 갑자기 힙의 절반을 볼 수 없다는 사실을 걱정할 필요가 없습니다.

디자인을 자세히 살펴보면 다양한 실패 사례를 어떻게 처리할지에 따라 결정될 것이라고 생각합니다.

의견에 대한 응답:

귀하의 질문은 .NET Remoting 및 CORBA가 다루는 분산 방식으로 개체를 저장하는 방법에 대해 설명합니다.물론 두 기술 모두 이러한 개체(AFAIK)의 마이그레이션을 지원하지 않습니다.그러나 둘 다 분산 개체 시스템의 중요한 부분인 개체 정체성의 개념을 광범위하게 다루고 있습니다.시스템의 다양한 부분이 어떤 개체에 대해 이야기하고 있는지 어떻게 알 수 있습니까?

저는 Java 가비지 수집기의 세부 사항에 대해 잘 알지 못하며 Java 및 .NET 가비지 수집기는 애플리케이션에 최소한의 영향을 미치면서 최대 성능을 달성하기 위해 많은 복잡성을 갖고 있다고 확신합니다.

그러나 가비지 수집의 기본 아이디어는 다음과 같습니다.

  • VM은 모든 스레드의 관리 코드 실행을 중지합니다.
  • 알려진 '루트' 집합에서 연결 가능성 분석을 수행합니다.정적 변수, 모든 스레드의 지역 변수.각 개체에 대해 개체 내의 모든 참조를 따릅니다.
  • 도달성 분석으로 식별되지 않은 모든 개체는 가비지입니다.
  • 아직 살아있는 개체는 메모리 아래로 이동하여 조밀하게 압축할 수 있습니다.이는 이러한 개체에 대한 모든 참조도 새 주소로 업데이트되어야 함을 의미합니다.가비지 수집이 발생할 수 있는 시기를 제어함으로써 VM은 '공중' 개체 참조가 없음을 보장할 수 있습니다(예:기계 레지스터에 보관되어 있는 경우) 문제가 발생할 수 있습니다.
  • 프로세스가 완료되면 VM은 스레드 실행을 다시 시작합니다.

이 프로세스를 개선하여 VM은 개체의 '연령'을 기준으로 별도의 힙이 유지 관리되는 세대별 가비지 수집을 수행할 수 있습니다.개체는 힙 0에서 시작하고 여러 GC에서 살아남으면 힙 1로 마이그레이션되고 결국 힙 2로 마이그레이션됩니다(그래서 .NET은 3세대만 지원함).이것의 장점은 GC가 힙 0 컬렉션을 매우 자주 실행할 수 있고 수명이 긴 객체(힙 2에 도달함)가 아직 살아 있음(거의 확실함)을 증명하기 위한 작업을 수행하는 것에 대해 걱정할 필요가 없다는 것입니다. .

동시 가비지 수집을 지원하기 위한 다른 개선 사항과 GC가 예약될 때 실제로 관리되지 않는 코드를 실행하는 스레드에 대한 세부 정보가 있어 이 영역에 훨씬 더 복잡성이 추가됩니다.

귀하의 요구 사항에 대해 더 알고 싶습니다.또 다른 답변에서 알 수 있듯이 테라코타가 바로 귀하가 찾고 있는 것일 수 있습니다.

그러나 Terracotta가 제공하는 것과 귀하가 요구하는 것 사이에는 미묘한 차이가 있으므로 문의드립니다.

차이점은 사용자가 생각하는 한 Terracotta는 객체에 대한 "원격" 참조를 제공하지 않는다는 것입니다. 실제로는 RMI, JMS 등의 전체 "원격" 개념입니다.테라코타를 사용할 때는 전혀 없습니다.

오히려 Terracotta에서는 모든 객체가 큰 가상 힙에 상주합니다.노드 1, 노드 2, 노드 3, 노드 4 등의 스레드는 모두 가상 힙의 모든 개체에 액세스할 수 있습니다.

학습할 특별한 프로그래밍이나 특별한 API가 없으며 "가상" 힙의 개체는 로컬 힙의 개체와 정확히 동일한 동작을 갖습니다.

간단히 말해서 Terracotta가 제공하는 것은 단일 JVM에 대한 프로그래밍 모델과 정확히 동일하게 작동하는 여러 JVM에 대한 프로그래밍 모델입니다.별도의 노드에 있는 스레드는 단순히 단일 노드에 있는 스레드처럼 동작합니다. 개체 변형, 동기화, 대기, 알림은 모두 스레드 전체에서와 마찬가지로 노드 전체에서 정확히 동일하게 동작합니다. 차이가 없습니다.

또한 이전 솔루션과 달리 객체 참조는 노드 전체에 걸쳐 유지됩니다. 즉, ==를 사용할 수 있습니다.이는 모두 "일반" Java(예:POJO, 동기화, 대기/알림) 작동(클러스터 전체에서 객체 ID를 보존하지 않거나 유지할 수 없는 경우 그 중 아무 것도 작동하지 않습니다).

따라서 요구 사항을 더욱 구체화하기 위한 질문이 다시 돌아옵니다. 어떤 목적으로 "원격" 포인터가 필요합니까?

당신이 추구하는 키워드는 "가비지 수집기 압축"입니다.JVM은 하나를 사용하도록 허용됩니다. 이는 객체를 재배치할 수 있음을 의미합니다.JVM 매뉴얼을 참조하여 JVM 매뉴얼을 참조하여 JVM 매뉴얼에 영향을 미치는 명령줄 옵션이 있는지 확인하세요.

압축을 개념적으로 설명하는 가장 간단한 방법은 가비지 수집기가 모든 스레드를 동결하고 개체를 재배치하며 해당 개체에 대한 모든 참조에 대해 힙과 스택을 검색하고 새 주소로 업데이트한다고 가정하는 것입니다.실제로는 그보다 더 복잡합니다. 성능상의 이유로 스레드가 정지된 상태에서 전체 스윕을 수행하고 싶지 않기 때문에 증분 가비지 수집기는 가능할 때마다 압축 준비 작업을 수행합니다.

간접 참조에 관심이 있다면 Java의 약한 참조와 소프트 참조, 그리고 다양한 RPC 시스템에서 사용되는 원격 참조를 조사하는 것부터 시작할 수 있습니다.

terracotta 또는 oracle의 java objece 캐시(이전의 Tangersol)와 같은 분산 캐시를 찾고 있는 것 같습니다.

더 깊이 들어가고 싶다면 JBoss Cache 아키텍처 문서를 살펴보고 해당 소스 코드 중 일부를 참조로 가져오세요.

이것은 정확히 설명하신 내용은 아니지만 매우 유사하게 작동합니다.

링크는 다음과 같습니다.

http://www.jboss.org/jbosscache/

이게 도움이 되길 바란다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top