우수한 Java 프로그래머는 GC의 작동 방식, GC의 성능을 최적화하는 방법 및 GC와의 상호 작용이 제한적인 방법을 이해해야합니다. 일부 응용 프로그램에는 임베디드 시스템, 실시간 시스템 등과 같은 고성능 요구 사항이 있기 때문입니다. 메모리 효율을 관리 하여만 포괄적으로 개선하면 전체 응용 프로그램의 성능이 향상 될 수 있습니다. 이 기사는 먼저 GC의 작업 원칙을 간략하게 소개 한 다음 GC의 몇 가지 주요 문제에 대한 심층적 인 토론을 수행하고 결국 GC 관점에서 Java 프로그램의 성능을 향상시키기 위해 일부 Java 프로그래밍 제안을 제시합니다.
GC의 기본 원리
Java의 메모리 관리는 실제로 객체의 할당 및 릴리스를 포함하여 객체의 관리입니다.
프로그래머의 경우 새 키워드는 객체를 릴리스 할 때 객체에 대한 모든 참조가 NULL에 할당되므로 객체에 액세스 할 수 없습니다. .GC는 모든 /"도달 할 수없는 /"객체의 메모리 공간을 회수 할 책임이 있습니다.
GC의 경우 프로그래머가 객체를 생성 할 때 GC는 객체의 주소, 크기 및 사용을 모니터링하기 시작합니다. 일반적으로 GC는 지시 된 그래프를 사용하여 힙의 모든 객체를 기록하고 관리합니다 (자세한 내용은 참조 1 참조). 이러한 방식으로, 어떤 객체가 /"도달 가능 /"이고 어떤 객체가 /"도달 할 수없는 /"인지 결정할 때 /"도달 할 수없는 /". 그러나 GC를 다른 플랫폼에서 구현할 수 있도록 Java 사양은 GC의 많은 동작을 엄격하게 규정하지 않습니다. 예를 들어, 사용할 재활용 알고리즘 유형 및 재활용을 수행 할시기와 같은 중요한 문제에 대한 명확한 규정은 없습니다. 따라서 다른 JVM 구현자는 종종 다른 구현 알고리즘을 갖습니다. 이것은 또한 Java 프로그래머의 개발에 불확실성을 가져옵니다. 이 기사는 GC 작업과 관련된 몇 가지 문제를 조사하고 Java 프로그램에 대한 이러한 불확실성의 부정적인 영향을 줄이기 위해 노력합니다.
증분 GC (증분 GC)
GC는 일반적으로 하나 또는 프로세스 그룹에 의해 구현됩니다. GC 프로세스가 실행될 때 CPU를 차지합니다. 따라서 GC가 오랫동안 실행되면 사용자는 Java 프로그램의 일시 정지를 느낄 수 있습니다. 여전히 재활용되지 않은 많은 물체는 여전히 많은 기억을 취합니다. 따라서 GC를 설계 할 때 일시 정지 시간과 복구 속도를 측정해야합니다. 좋은 GC 구현을 통해 사용자가 필요한 설정을 정의 할 수 있습니다. 다른 실시간 온라인 게임은 프로그램에 장기간 중단을 허용 할 수 없습니다. 증분 GC는 특정 재활용 알고리즘을 통해 장기간 인터럽트를 많은 작은 인터럽트로 나누어서 GC가 사용자 프로그램에 미치는 영향을 줄이는 것입니다. 증분 GC가 전체 성능에서 일반 GC만큼 효율적이지는 않지만 프로그램의 최대 일시 중지 시간을 줄일 수 있습니다.
SUN JDK가 제공하는 핫스팟 JVM은 증분 GC의 기본 GC 메소드를 지원하여 증분 GC를 시작할 수 있습니다. 핫스팟 JVM 증분 GC의 구현은 Train GC 알고리즘을 사용하는 것입니다. 기본 아이디어는 생성 및 사용에 따라 힙에 (계층 적으로) 모든 객체를 그룹화하고, 대기열에서 빈번하고 관련성이 높은 사용을 가진 객체를 넣고, 프로그램이 조정을 실행함에 따라 계속 그룹화하는 것입니다. GC가 실행되면 항상 가장 오래된 (최근에 방문한) 객체를 먼저 재활용하며 전체 그룹이 재활용 가능한 객체 인 경우 GC가 전체 그룹을 재활용합니다. 이러한 방식으로, 각 GC 실행은 프로그램의 원활한 작동을 보장하기 위해 특정 비율의 도달 할 수없는 객체 만 재활용합니다.
최종 기능에 대한 자세한 설명
Finalize는 객체 클래스에 위치한 방법입니다. 최종 기능은 체인 호출을 자동으로 구현하지 않으므로 수동으로 체인 호출을 구현해야하므로 최종 기능의 마지막 명령문은 일반적으로 super.finalize ()입니다. 이런 식으로, 우리는 맨 아래에서 맨 위로 마무리를 구현하기위한 호출을 구현할 수 있습니다.
Java Language Specification에 따르면, JVM은 최종 기능을 호출하기 전에이 객체를 연락 할 수 없도록 보장하지만 JVM 은이 기능이 호출 될 것이라고 보장하지 않습니다. 또한 사양은 또한 최종 기능이 최대 한 번에 실행되도록합니다.
많은 Java 초보자는이 방법이 C ++의 소멸자와 유사하다고 생각할 것이며이 기능에서 많은 객체와 리소스의 출시를 제공합니다. 사실, 이것은 좋은 방법이 아닙니다. 세 가지 이유가 있습니다. 먼저, 최종 기능을 지원하기 위해 GC는이 기능을 다루는 객체에 대해 많은 추가 작업을 수행해야합니다. 둘째, 최종 실행이 완료된 후에는 객체에 도달 할 수 있으며 GC는 객체에 도달 할 수 있는지 다시 확인해야합니다. 따라서 Finalize를 사용하면 GC의 성능이 줄어 듭니다. 셋째, GC 통화가 Finalize가 불확실한시기이기 때문에 이러한 방식으로 리소스를 공개하는 것도 확실하지 않습니다.
일반적으로 Finalize는 제어하기 쉽고 일부 I/O 운영 및 데이터 연결과 같이 매우 중요하지 않은 일부 리소스를 해제하는 데 사용됩니다. 이러한 리소스의 출시는 전체 응용 프로그램에 매우 중요합니다. 이 경우 프로그래머는 주로 프로그램 자체를 통해 이러한 리소스를 관리하고 (출시 포함) 주로 자원을 릴리스하기 위해 마무리하는 데 의존하는 대신 이중 보험 관리 메커니즘을 형성하기위한 보충제로서 자원을 공개하는 방법을 보충해야합니다.
다음은 최종 기능을 호출 한 후에도 여전히 도달 할 수 있음을 설명 할 수 있습니다.
클래스 myObject {테스트 메인, 테스트 객체를 기록합니다. /이 객체에 도달 할 수 있도록이 객체를 복원하십시오. out.println (/"이것은 마무리/"); // 한 번만 실행하기 위해 마무리하는 데 사용됩니다} 클래스 테스트 {myObject ref; ] ARGS) {test = new myObject (test); .ref! = null) system.out.println (/"내 객체는 여전히 살아있다")};
실행 결과 :
이것은 마무리됩니다
myObject는 여전히 살아 있습니다
이 예에서는 MyObject 객체가 Finalize에서 도달 가능한 객체가되지만 다음에 재활용 할 때는 최종 기능이 최대 한 번만 호출되므로 Finalize는 더 이상 호출되지 않습니다.
프로그램이 GC와 상호 작용하는 방법
Java2는 메모리 관리 기능을 향상시키고 Java.lang.ref 패키지를 추가하여 3 개의 참조 클래스를 정의합니다. 이 세 가지 참조 클래스는 이러한 참조 클래스를 사용하여 Softreference, 약한 회의 및 Phantomreference입니다. 이러한 참조 클래스의 참조 강점은 도달 가능성과 도달 할 수없는 객체 사이에 있습니다.
예를 들어, 소프트 참조 객체를 만들고 먼저 객체를 작성해야합니다 NULL에 대한 일반적인 참조를 설정하면 객체에는 하나의 소프트 참조가 있습니다. 동시에, 우리는이 개체를 부드러운 기준 객체라고 부릅니다.
소프트 참조의 주요 특징은 강력한 인용 기능이 있다는 것입니다. 이 유형의 메모리는 메모리가 불충분 할 때만 재활용되므로 메모리가 충분하면 일반적으로 재활용되지 않습니다. 또한, Java가 Outfemory 예외를 발생시키기 전에 이러한 기준 객체는 NULL으로 설정할 수 있습니다 다음은이 참조 유형에 대한 pseudocode 사용입니다.
// 이미지 객체 이미지 = 새 이미지 (); // 이미지 생성 ... // 이미지를 사용한 후 소프트 참조 유형으로 설정하고 SOFTREFERENCE SR을 해제합니다 = New SofTreference (이미지);… 다시로드해야합니다.
약한 참조 객체와 소프트 참조 객체의 가장 큰 차이점은 GC 재활용시 소프트 참조 객체가 재활용되는지 여부를 확인하기 위해 알고리즘을 사용해야하는 반면 GC는 항상 약한 기준 객체를 재활용한다는 것입니다. 약한 기준 객체는 GC에 의해 더 쉽고 빠릅니다. GC는 실행할 때 약한 물체를 재활용해야하지만 복잡한 관계를 가진 약한 물체 그룹은 종종 여러 GC 실행이 완료되어야합니다. 약한 기준 객체는 맵 구조에서 종종 객체의 강력한 참조가 널이되면 객체 공간을 빠르게 재활용 할 수 있습니다.
팬텀 참조는 덜 유용하며 주로 최종 기능 사용을 지원하는 데 사용됩니다. 팬텀 객체는 최종 기능을 완료하고 도달 할 수없는 객체 인 일부 객체를 말하지만 GC에 의해 재활용되지 않았습니다. 이러한 종류의 객체는 나중에 재활용 작업을 마무리 할 수 있습니다.
일부 Java 코딩 제안
GC의 작업 원칙에 따르면, 우리는 일부 기술과 방법을 사용하여 GC가 응용 프로그램의 요구 사항에 따라보다 효율적이고 더 많은 것을 실행하도록 할 수 있습니다. 프로그래밍에 대한 몇 가지 제안이 있습니다.
1. 가장 기본적인 제안은 가능한 한 빨리 쓸모없는 물체의 참조를 공개하는 것입니다. 대부분의 프로그래머는 임시 변수를 사용하면 활성 도메인을 종료 한 후 기준 변수를 자동으로 설정합니다. 그래프 등은이 객체 사이에 복잡한 관계가 있습니다. 그러한 물체의 경우 GC는 일반적으로 덜 효율적입니다. 프로그램이 허용되면 사용하지 않은 참조 객체를 가능한 빨리 NULL에 할당하십시오. [페이지]
2. 최대한 적은 마무리 기능을 사용해보십시오. Finalize 기능은 Java가 프로그래머에게 객체 나 리소스를 릴리스 할 수있는 기회를 제공 할 수있는 기회입니다. 그러나 GC의 워크로드가 증가 할 것이므로 가능한 한 적은 마무리를 사용하여 리소스를 재활용하십시오.
3. 자주 사용되는 사진을 사용해야하는 경우 소프트 응용 프로그램 유형을 사용할 수 있습니다. 프로그램이 외부에서 유발하지 않고 호출 할 수 있도록 최대한 메모리에 이미지를 저장할 수 있습니다.
4. 배열, 트리, 그래프 및 링크 된 목록과 같은 데이터 구조를 포함하여 수집 데이터 유형에주의하십시오. 또한 일부 글로벌 변수와 일부 정적 변수에주의하십시오. 이러한 변수는 쉽게 매달려있는 참조를 유발하여 메모리 폐기물을 유발하는 경향이 있습니다.
5. 프로그램에 특정 대기 시간이있는 경우 프로그래머는 수동으로 System.gc ()를 실행하여 GC에 실행되도록 통지 할 수 있지만 Java 언어 사양은 GC가 실행되도록 보장하지 않습니다. 증분 GC를 사용하면 Java 프로그램의 일시 중지 시간이 단축 될 수 있습니다.