머리말
SegmentFault에 대한 질문을 보았습니다. Java는 완전한 GC 메커니즘을 가지고 있으므로 Java에 메모리 누출 문제가 생길 수 있으며 메모리 누출 사례를 줄 수 있습니다. 이 질문보기는이 질문에 대한 완전한 답변을 제공합니다.
쓰레기 재활용 메커니즘 소개
프로그램을 실행하는 동안 각 객체가 생성되며 객체 데이터를 저장하기 위해 일정량의 메모리가 할당됩니다. 메모리를 계속 할당하면 프로그램은 조만간 메모리가 불충분 한 문제에 직면하게됩니다. 따라서 모든 언어에서는 메모리를 재사용 할 수 있도록 만료 된 객체의 메모리를 확보하기위한 메모리 복구 메커니즘이 있습니다.
메모리 재활용 메커니즘은 구현 역할에 따라 두 가지 유형으로 나눌 수 있습니다. 하나는 프로그래머가 수동으로 메모리의 출시 (예 : C 언어)를 인식하고 다른 하나는이 기사에서 소개 할 Java Garbage Collection 메커니즘과 같은 언어의 내장 메모리 재활용 메커니즘이라는 것입니다.
자바의 쓰레기 수집 메커니즘
이 프로그램의 런타임 환경에서 Java Virtual Machine은 시스템 수준의 쓰레기 수집 (GC, Carbage Collection) 스레드를 제공하며, 이는 참조를 잃은 객체가 차지하는 메모리를 되 찾는 책임이 있습니다. GC를 이해하기위한 전제 조건은 쓰레기 수집과 관련된 몇 가지 개념을 이해하는 것입니다. 이 개념은 다음 중 하나씩 소개됩니다.
JVM 힙 영역의 물체 상태
Java 객체의 인스턴스는 JVM의 힙 영역에 저장됩니다. GC 스레드의 경우이 객체에는 3 개의 상태가 있습니다.
1. 터치 가능한 상태 : 프로그램에는 가변 참조가 있으므로이 개체는 접을 수 있습니다.
2. 재 활성화 된 상태 : 프로그램의 변수 가이 객체를 언급 할 때, 객체는 터치 가능한 상태에서 재 활성화 된 상태로 변경됩니다. CG 스레드는 특정 시간 에이 객체의 마무리 메소드를 호출 할 준비를합니다 (마무리 메소드는 Child Object를 상속하거나 재 작성). 최종 방법의 코드는 객체를 터치 가능한 상태로 변환 할 수 있으며, 그렇지 않으면 객체가 만질 수없는 상태로 변환됩니다.
3. 만질 수없는 상태 : GC 스레드는 객체가 만질 수없는 상태에있을 때만이 객체의 메모리를 재활용 할 수 있습니다.
객체를 올바르게 방출하려면 GC는 응용 프로그램, 인용, 인용, 할당 등을 포함하여 각 객체의 실행 상태를 모니터링해야합니다. GC는이를 모니터링해야하므로 GC는 위의 상태에 있는지 여부를 알 수 있습니다.
위에서 언급했듯이 GC 스레드는 특정 시간에 부활 가능한 상태 객체의 최종 방법을 실행합니다. 그렇다면 언제 실행됩니까? 다른 JVM 구현자는 다른 알고리즘을 사용하여 GC를 관리 할 수 있으므로 언제든지 개발자는 다양한 작업을 수행하는 GC 스레드의 타이밍을 예측할 수 없기 때문에 (개체 상태 감지, 객체 메모리 방출 및 객체 최종 메소드를 호출). GC 스레드는 System.gc () 및 runtime.gc () 함수를 통해 가능한 빨리 쓰레기 수집 작업을 수행하도록 상기시킬 수 있지만 GC 스레드가 해당 재활용 작업을 즉시 수행 할 것이라고 보장 할 수는 없습니다.
메모리 누출
메모리 누출은 프로그램이 더 이상 사용되지 않는 메모리를 해제하지 못하여 자원 낭비를 초래한다는 잘못된 설계로 인해 발생합니다. GC는 참조를 잃은 객체가 차지하는 메모리를 자동으로 정리합니다. 그러나 프로그래밍 오류로 인해 일부 객체가 항상 참조되는 경우 메모리 누출이 발생합니다.
예를 들어 다음 예제입니다. 배열은 스택 입력과 스택 종료의 두 가지 작업이있는 스택을 구현하는 데 사용됩니다.
import com.sun.javafx.collections.elementobservablelistdecorator; import com.sun.swing.internal.plaf.metal.resources.metal_sv; import java.beans.xceptionlistener; import java.util.emptystackexception;/*** 14-9-21에서 작성했습니다. */public class mystack {private 객체 [] 요소; 개인 int 증분 = 10; 개인 int 크기 = 0; public mystack (int size) {elements = new Object [size]; } // 스택을 공개 void push (object o) {faction (); 요소 [size ++] = O; } // 스택 공용 객체를 넣습니다. pop () {if (size == 0) 새 nick emptystackexception (); 반환 요소 [-크기]; } // 스택의 용량 증가 개인 무효 용량 () {if (elements.length! = size) return; Object [] newArray = new Object [elements.length + ycrement]; System.ArrayCopy (요소, 0, NewArray, 0, 크기); } public static void main (String [] args) {mystack stack = new Mystack (100); for (int i = 0; i <100; i ++) stack.push (새 정수 (i)); for (int i = 0; i <100; i ++) {system.out.println (stack.pop (). toString ()); }}}이 프로그램은 사용할 수 있으며 공통 스택 항목 및 스택 입력 작업을 지원합니다. 그러나 잘 처리되지 않은 문제가 있습니다. 즉, 스택 작업이 해제되면 배열의 스택 요소에 대한 참조가 해제되지 않으므로 프로그램 이이 객체에 대한 참조를 유지하게합니다 (이 개체는 배열에 의해 참조됩니다). GC는 항상이 객체에 액세스 할 수 있다고 생각합니다. 즉, 메모리를 공개하는 것에 대해 이야기 할 필요가 없습니다. 이것은 전형적인 메모리 누출의 경우입니다. 이를 위해 수정 된 코드는 다음과 같습니다.
// public Object POP () {if (size == 0) 새 nick emptystackexception (); 개체 o = 요소 [-크기]; 요소 [size] = null; 반품 o; }위의 기사는 Java Garbage Collection 메커니즘 및 메모리 누출을 깊이 이해하고 있습니다. 이것은 내가 당신과 공유 한 모든 콘텐츠입니다. 나는 그것이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.