GC 기술, 암호 해독 형이상학 적 이론 가비지 컬렉션에 대한 뭔가의 (a)

이상 OOM, GC 일시 정지, 이러한 이상 당신이 적시에 치료를받을 수없는 경우, 심각하게 응용 프로그램의 성능에 영향을 미칠 것입니다, 가난한 사용자 경험에 직접 이어질 : GC의 일상 개발에 대부분의 프로그래머는 종종 문제가 발생. 이 시리즈는 GC 기반 및 다양한 기술과 문제 GC의 루트에 대해 잘 알고 점차 도움말 독자들과 시작합니다.

GC의의 기원

먼저, Pangu ......

음, 풀 떨어진이되지 시안 쌰 소설입니다 ...

결국 GC 와서 어떻게? 프로그램을 작성할 때 우리 모두 알다시피, C / C ++는 언어, 당신은 malloc에 ​​시간을 사용하는 것입니다 코드를 자신이 관리하는 신 메모리, 시각 메모리, 필요, C 언어에서이 문제에 대해 담소를 나눴다,이 메모리는 항상 예약한다 프로그램 과정, 프로그램이 명시 적으로 해제됩니다 무료로 호출 할 때까지.

문제점의 예에 의한

//第 0 步: char* aMem;
//第 1 步:
aMem = (char*) malloc(sizeof(char) * 1024);
//第 2 步:
strcpy(aMem, "I am a bunch of memory");
//第 3 步:
free(aMem);
复制代码

3 단계와 같은 냉장고에 코끼리 참조하지 :

  1. 비어있을 경우 냉장고 문을 열고, 참조 : malloc에 ​​공간이 응용 프로그램을 사용하여.
  2. 코끼리는 냉장고에 넣어 : strcpy를 복사 문자열을 공간에.
  3. 닫기 냉장고 문 : 사용, 무료 또한 메모리에 다시하지 않을 때 (엄격한 말하자면,이 메이크업 룸 냉장고에 처음 코끼리 밖으로해야, 다음 번에 코끼리에 대비하여 재무장 할 수 있습니다).

그것은 간단하지 않다? 당신이 malloc에 ​​메모리를 적용해야하는 경우, 사용 가능한 메모리는 출시 후 소진. 그러나 사실은 많은 문제, 단계별로 단계에서 살펴 보자으로 이어질 수, 3 줄의 코드로 간단하다 :

질문 1 : 상기 단계는 0이 될 경우 AMEM = (CHAR * )의 malloc (sizeof 연산자 (숯)), 바로 실행 입력란 1 문제가 언제인가?

A는 : 순서의 해제를 다시 사용하기 위해 할당 될 후 전체 프로세스가 완료 될 때까지, 다음 프로그램이이 메모리를 점유 항상 자유 의지하지 않으면 메모리 누수, 메모리 malloc에 ​​모든 응용 프로그램은 무료로해야합니다. 프로그램 로직 실행이 아무 문제 없지만, 비록 메모리 나중에 프로그램에서 아마 밖으로 메모리 문제의 너무 많이 묻은 경우, 알 수없는 오류의 다양한 결과. 또한 유의해야하다의 malloc aMem, 리턴 어드레스를 가정하고 (여기에서의 malloc 1 단계는 aMem 공간 할당 (어드레스 aMem = 0x1234 하였다 가정)으로 할당 된 공간을 스텝 0 aMem = malloc에 ​​있다면 0x5678), 즉, 공간의 일부에 0x1234 포인트를 점유하고있다,라고하는 효과적인 수단으로이 주소를 얻기 위해 다음 프로그램이 실제로없는, 그것을 확보 할 수있는 방법은 없습니다. 합니다 (aMem이 0x5678로 변경 될 수 있기 때문에) 때문에 프로그램이 종료되지 않는 한, 그렇지 않으면 우리는 공간이 0x1234이 뾰족한 해제 할 기회가 없다.

질문 2 : 시스템이 너무 많은 빈 공간이없는 경우에 실제로, 1024 바이트의 공간에 적용되는 문제는 무엇인가?

A : 직접 오류는이 메모리 누수를 조사 할 시간이 없습니다.

질문 3 : 문자열의 사본이없는 경우 "I 메모리의 무리이다", 그러나 "... 1025 1,2,3,4는"무슨 일이 일어날 것인가?

A : strcpy와는 (포함 '\ 0') 1,026 문자, 즉 메모리가 오염 로케이션 제 1024 자 malloc이 밖으로 나오 있지만, 이것은 광 메모리 이끌 여기서 경계는 검사를 수행하지 않기 때문에 오버 플로우, 불순한 동기 및 프로그램에 사람들이 당신의 작은 비밀처럼 모든 정보 덤프 아웃 ... 넣을 수 있다면 ...

질문 4 : 응용 프로그램 전에 대한 기억이 성공하지 않는 경우, 무료로 어떤 문제 3 단계?

A :이 malloc에 ​​전에 실패 할 경우 오류가, 두 번째 단계는 실제로 잘못된 것입니다. malloc이 오류가 발생할 경우에는 두 번째 단계가 없다는 가정하에, 무료 프로그램이 직접적으로 충돌합니다 호출합니다.

질문 5 : 어떤 두 번 무료가 전화하면 어떻게됩니까?

A는 : 같은 오류가 발생,이 두 가지 무료 알 수없는 오류, 또는 프로그램 충돌이 발생합니다.

질문 6 : 만약이,이 무료 한 후, aMem의 값이 무엇인지 내부에 보관?

A : 자유는 값 aMem을 수정하지 않는 한 후 경우 malloc을 반환 0x1234 이전에 이렇게 무료 여기 aMem, aMEM 또는 0x1234합니다. 0x1234 문제가 될 것, 상상 경우 aMem 액세스 후자도?

GC의 중요성

일부는 말할 수 : 여섯 개 질문 위 한 내가 malloc에와 라인에 자유롭게 사용할 수를 보장 할 수있는, 완전히 피할 수 있습니다. 현실 정말 너무 멋진 경우, 모든 것이 잘 될 것입니다. 불행하게도, 현실은 이러한 코드와 같은 더 복잡한 절차이며, 존재의 1000 개 라인의 경우 ... 다른 ...,에 / 루프 위의 문제가 발생하기 쉬운 것입니다 동안. 일일 트래픽 제품이 일정 수준에 도달 할 때까지 메모리 누수가, 천천히 축적, 모르는 장소에서 일반적으로 매복 된 후, 서비스 프로세스가 갑자기 붕괴 할 것이다. 더욱 무서운 우리는 종종 어디에서 메모리가 누수 위치하는 효과적인 분석 방법 (온라인 또는 고급 디버깅 도구) 부족 때문이다.

그래서 엄격하게 프로그래밍 표준을 적용 할뿐만 아니라, 메모리가 누출 줄일 수있는 다른 방법이 있습니까? 일부 대형 가축 수있는 방법을 생각 : 할당 및 메모리 사용에 대한 책임이있는 프로그래머가, 사용 가능한 메모리의 출시가 자유 낙하이되지 않는 메모리를 넣어 자동으로 식별하고 책임이있는 컴퓨터가 필요합니다. 그래서 긴 프로그래머의 malloc / 새와 같은 무료 / 삭제가 필요하지 않습니다. 컴퓨터를 식별하고 사용되지 않는 메모리 (쓰레기)을 회수 할 수 있다면, 한 손에 메모리 누수가 아닌 미야의 가능성을 피할 반면에, 코드의 양을 줄이기 위해? 이것은 GC의 기원 자동 메모리 관리 개념의 기원입니다.

이제 우리는 다음과 같은 두 가지 측면을 포함하는 바,의 GC의 중요성을 이해한다 :

  • 한편 코드 개발자의 비용을 줄일 수 있습니다. 개발자는 메모리 복구 프로그램은 메모리 사용량 논리에 대해 생각하는 시간을 줄일 수있는 방법에 대해 염려 할 필요가 없습니다.
  • 반면에 프로그램의 정확성을 보장합니다. 개입 개발자없이, 메모리 누수와 같은 인간의 생성뿐만 아니라 컴퓨터 프로그램의 정확성을 확인하는 등의 오류가없는 다양한 문제를 줄일 수있다. 프로그램은 더 강력 할뿐만 아니라 한밤중가 얻을 수있는 문제 해결 운영 및 유지 보수 인력의 기회를 줄 것입니다.

GC 알고리즘

하자의 검토는 GC 반짝 알고리즘 내부의 다양한 소 : 사실의 참조 계수, 마크 스윕, 동시 마크 스윕, 세대 동시 마크 스윕 등, 이러한 알고리즘은 크게 두 가지 범주로 나눌 수 있습니다 :

  • 하나는 재활용, 쓰레기를 찾는 것입니다.

  • 또, 객체가 쓰레기없는 찾을 예약입니다. 나머지는 그들을 재활용, 쓰레기 객체입니다.

레퍼런스 카운팅 (참조 횟수) 및 객체 추적 (객체 추적) 결과 현재 GC 알고리즘은 두 가지 카테고리로 나누어진다. 오늘, 우리는 주로 참조 횟수에 대해 이야기.

참조 카운팅

레퍼런스 카운트 (참조 횟수)는 검색 가비지 목적 및 복구 알고리즘이다. 대략적으로 말하면, 쓰레기 개체를 말한다 더 이상 객체 액세스 프로그램, 단어의 특정 세그먼트, 실제로는 여전히 두 가지 범주로 나누어 져 있습니다 "개체가 더 이상 프로그램에 액세스 할 수있는"존재하지 않습니다. 자, 우리가 고문 영혼 일단 객체하자 : 당신은 어떤 종류의 쓰레기를입니까?

Object가 프로그램에 더 이상 액세스 할 수 없습니다, 그것은 두 가지 특정 범주로 나눌 수 있습니다

1. 목적도없는 액세스 할 수 있지만, 프로그램 후 더 이상 사용됩니다.

예를 들면 :

public class A {

private void method() {
   System.out.println("I am a method");
}

public static void main (String args[]) {
    A a1 = new A();
    A a2 = new A();
    a1.method();
    // The following code has noting to do with a2
    ....
    .... // a2.method();
}
}
复制代码

이 경우 내부, A2에 액세스 할 수 있지만, 나중에 프로그램에서 사용하지 않습니다. 프로그램 논리의 관점에서,이 객체는 쓰레기 A2 지점이지만, 컴퓨터에서이 쓰레기 "정크가 아님." 프로그램이 갑자기 후회하는 경우 뒤에 (예 : 주석 내부 코드의 마지막 줄)이 객체에게 A2를 사용하고자하기 때문에, 프로그램은 여전히 ​​개체에 대한 일반 액세스 할 수 있습니다. 컴퓨터의 관점에서 그래서, A2 뾰족한 물체는 쓰레기가 아닙니다.

우리가 의심 수도, 여기를 참조하십시오 : 코드가 주석하고있다 a2.method을 (), 다음 프로그램은 확실히이 경우, 객체 A2 참조 또는 쓰레기에,이 코드를 실행하지 않습니다 왜 컴퓨터 만의 관점에서 A2 객체 스팸?

사실, 우리는 그래서 당신은 액세스 여전히 할 수있는, 많은 코드가 완전히 실행 a2.method () 바이트 코드 삽입 등의 자바 바이트 코드 수단으로 동적 언어를 지원하도록 변경해야합니다. 또한,이 코드의 논리 함수 스택 A2에, 힙에서 참조 A2 개체가 너무 오래 A2는 프로그램에 볼 수 있습니다이 객체를 인용 한 바와 같이, 컴퓨터는이 때문에, 스팸 생각하지 않습니다 폐기물은 재활용 재료를하지 않습니다.

컴퓨터 : 난 당신이 나에, 나는 생각합니다 생각하지 않습니다!

2. 개체에 액세스되지 않은 프로그램이 찾을 수있는 방법이 없기 사용하고 싶습니다.

당신에게 예를 보내기

public class A {

private void method() {
   System.out.println("I am a method");
}

public static void main (String args[]) {
    A a1 = new A();
    A a2 = new A();
    a1.method();
    // The following code has noting to do with a2
    ....
    ....
    a2 = a1;
}

}
复制代码

그리고 앞의 예는 거의 동일하지만, 우리는 마침내 A1 A2에 할당. 다음은 A2 값은 원래 개체가 참조하는 다른 아무것도 없다 A2 객체 뾰족한 A2는 A1 점의 대상이 될 것으로 변경했다,이 후 프로그램 액세스 그것에 방법이 없습니다. 그래서 진짜 쓰레기가됩니다. 아래를 참조하십시오 :

우리는 종종 쓰레기 수집 기술을 말하는 그래서, 주로 객체를 처리하는 데 사용됩니다. 질문은 그래서, 어떻게이 개체를 찾는 방법은? 참조 횟수 : 이전의 아이디어에 따라, 더 이상 아무것도에 의해 참조되는 객체 수 없습니다, 그것은 간단하고 직관적 인 복구 알고리즘을 다음과 재활용 폐기물이다.

참조 카운트의 개념, 위키 백과의 설명 :

컴퓨터 과학, 레퍼런스 카운트는 오브젝트 메모리 블록, 디스크 공간과 같은 다른 자원을 참조하는 포인터, 또는 핸들의 번호를 저장하는 프로그래밍 기법이다.

그것은 단순히 다음과 같다 :

  • 모든 개체는 짧은 데이터의 기록에서, 데이터 구조를 분리 할 수 ​​있고, 대상이 될 수있는 기준 기록을 카운트하는 카운터가 존재한다.
  • 모든 개체 (예 신품)이 생성되면, 레퍼런스 카운트는 1이다.
  • 가변되거나 언급 된 하나의 레퍼런스 카운트를 실시 다른 목적이 때이다.
  • 다른 경우 오브젝트 변경에 대한 참조는 객체는 이전 레퍼런스 카운트 인용 -1.
  • 기준 카운트가 0 인 경우 재활용 목적

당신은 읽을 수 없습니다? 그것은 코드를 중요하지 않습니다 :

public class A {

private void method() {
   System.out.println("I am a method");
}

public static void main (String args[]) {
    // 假设每个对象有一个引用计数变量rc
    A a1 = new A(); // 在堆上创建对象A, A.rc++;
    A a2 = new A(); // 在堆上创建对象A1,A1.rc++;
    a2 = a1; // A1.rc--,if ( A1.rc == 0 ) { 回收A1 }, A.rc++;
} // 函数退出:
   // a1销毁, A.rc--;
   // a2销毁, A.rc--;
   // if ( A.rc == 0 ) { 回收A }
}
复制代码

나는 안 읽어? 위 :

여기에 읽기, 당신은 참조 계수의 핵심 원리를 이해한다. 그냥 카운터와 덧셈과 뺄셈 메모리의 번호를 복구 할 수 있습니다, 매우 간단 보인다. 그러나, 참조 횟수가 개인적으로 생각 큰 문제가 있다는 것을 참조 카운팅 알고리즘의 핵심 문제 : 순환 참조.

순환 참조

다음의 의사를 고려 :

class Parent {
        Child child;
}

class Child {
       Parent parent;
}

public class Main {
     public static void main (String[] args) {
            Parent p = new Parent();
            Child c = new Child();
            p.child = c;
            c.parent = p;
     }
}
复制代码

그림은 이것이다 :

이 환상 참조 서로 인용 생성 동일한 참조 카운터는 1로 유지되고, 객체는 메모리 누출의 결과로 재생 될 수 없다. 당신은 요청할 수 있습니다 : 하나 개의 고리, 두 개체 할 일이 아닌가? 이 누수 메모리를 누설하지 않는 코드를 쓴 큰 문제가 아니다. 그러나 다음과 같은 상황이 발생할?

하나 개의 고리가 긴 작은 꼬리, 점차적으로 가출, 전체 체인에있는 모든 개체를 복구 할 수없는 OOM 예외, 시스템 붕괴, 코드, 결국 죽음을 힙 메모리가 발생합니다. 순환 참조 할의 어떻게 우리는이 문제를 해결합니까?

브로큰 말했다 반지

앞서 언급 한 바와 같이, 참조 카운팅 주요 연구 주제는 반지의 파괴에 참조됩니다. 내 생각에, 키는 다음과 같은 두 가지 모드가 있습니다 :

1. 추첨 용으로 나를 왼쪽 : 프로그래머 이동의 문제를

그것은 프로그래밍 언어 레벨을 여러 가지 방법을 제공하는 것입니다, API, 메모, 새로운 키워드 등, 다음 프로그래머의 반지를 파괴 할 수있는 능력이 될 수 있습니다.

스위프트 기준 또는 디폴트에 대하여 강한 C 포함한 weak_ptr를 같은 약한 / 바운드 키워드 ++, 제공되는 어떠한 기준이 수행되지 때 약한 참조 감소하지만, 참조 된 오브젝트가되어 회수 여부 모든되도록 결정되고 고리를 구성하는 참조 그렇게 간주되지 않는 고리를 구성하는 대향 부분에 약한 상관을들 수있다. 장점 등이다 일의 단점 :

장점 : 한 개수의 객체를 복구로, 환형 컴퓨터의 문제를 고려해야 할 필요가 없습니다.

단점 : 인식 프로그래머가 직접 메모리가 오버 플로우하지 않습니다 결정합니다. 프로그래머가 약한 키워드를 사용하지 않는 경우에는 상기 메모리 누수의 원인이 될 수 있습니다.

2. 다음 오른쪽은 무지개를 그립니다 : 이동 컴퓨터의 질문을

이러한 접근 방식은 컴퓨터가 순환 참조를 감지하는 자신의 방법을 찾을 수 있도록하는 것입니다, 일반적인 접근 방식은 추적 GC에 맞춰, 반지가 그들을 재활용, 반지 이외의 참조 된 개체를 찾을 수 없습니다입니다. 추적 GC는 후속 논의를 입었다. 만큼 우리는 순환 참조의 참조 횟수에 대한 도움말을 거래하기 위해, 여기에 이해, 컴퓨터가 적절한시기에 반지를 찾기 위해 별도의 알고리즘을 유발해야하며, 다음의 처리를 않습니다. 장점과 이렇게 단점 :

장점 : 완전히 프로그래머의 개입없이, 단지 달성하기 위해 자신의 비즈니스에 초점을 맞 춥니 다. 약한 포인터, 강력한 포인터는 중요하지 않습니다 말할 수 없습니다.

단점 : 프로그램에 새로운 원형 기준 감지 메커니즘, 알고리즘 복잡도 영향을 추가해야 할 문제이다.

우리는 요약했다 가졌 참조 횟수의 장점과 단점 :

장점 : 간단한 참조 카운팅 알고리즘 설계, 우리는 쓰레기가 될할지 여부를 결정할 수 있습니다 변경 개체를 참조 할 때 계산해야합니다. 그리고 객체의 실시간 복구를 수행 제로로 참조 횟수를 변경할 수 있습니다. 참조 횟수가 별도의 GC 단계입니다 그래서, 프로그램은 GC가 세계 무대를 중지 호출되지 않습니다.

단점 : 동작 프로그램 등, 객체, 할당 할 객체 멤버 변수를 생성하기 위해 계속 개체 변수를 변경 한 것입니다. 이 모든 작업은 +와의 도입을 필요로 -, 프로그램 성능은 필연적으로 영향을받습니다. (현재 최적화 방법이 도입 계수 참조 횟수의 문제를 줄이기 위해 컴파일러 최적화 기술을 사용하는 것입니다,하지만 완전히 피할 수 없습니다).

순환 참조는 어느 정도의 성능과 처리 과정에 영향을 미칠 것이다 세계 단계를 중지 프로그래머 처리 또는 컴퓨터 처리는 GC에 도입 될 수도있다, 프로그램의 복잡도가 증가인지를 상기 문제를 해결 양.

음! 여기에 이야기를 오늘은 어떻게 장례식,하자 듣고 다음 분해를 예측하는! 추적 GC, 현재 알고리즘의 클래스에서 널리 사용된다 : GC 알고리즘의 다른 클래스와 공유 다음번. 자바 스크립트 V8 여부, 안드로이드의 ART, 자바 핫스팟, OpenJ9, 또는 Golang GC의는 추적 GC 알고리즘을 채택했다.

저자 소개

ZANG 린, 텐센트 클라우드 미들웨어 JDK 사용자 정의 개발 및 최적화에 대한 책임 텐센트 클라우드 미들웨어 JVM 엔지니어. JVM이 메모리 관리에 초점, 런타임 및 클라우드 비즈니스 및 최적화 런타임 실행 엔진 성능 분석.

오픈 소스 프로젝트

텐센트 오픈 소스 JDK는 자바의 운영 능력을 향상, 텐센트 코나-8, 우리는 JDK 레벨에서 클라우드의 고충을 해결하기 위해 최선을 다하고 있습니다 프로젝트. 오픈 소스 링크 : github.com/Tencent/Ten ...

~ 당신과 만나 앞으로, 우리의 편지 공공 숫자로 살펴 관심의 마당을 청소에 오신 것을 환영합니다

추천

출처juejin.im/post/5e15bd6f6fb9a0484924c148