"안녕하세요! 가비지 수집에 대한 또 다른 작은 교훈을 주기로 결정했습니다."

이미 알고 있듯이 Java 머신 자체는 객체가 불필요해지면 이를 모니터링하여 삭제합니다.

"그래. 너랑 리시가 아까 얘기해줬어. 자세한 건 기억이 안 나."

"알았어. 그럼 다시 해보자."

가비지 컬렉션 - 1

"객체가 생성되자마자 JVM이 메모리를 할당합니다. 객체에 대한 관심은 참조 변수를 사용하여 모니터링됩니다.  가비지 수집, 즉 객체를 참조하는 변수가 없는 경우 메모리가 해제되는 절차 중에 객체를 삭제할 수 있습니다. 객체. "

"가비지 수집기가 무엇이며 어떻게 작동하는지에 대해 조금 말씀해 주십시오."

"좋습니다. 가비지 수집은 기본 스레드에서 발생했습니다. 5분마다 또는 더 자주. 사용 가능한 메모리가 충분하지 않으면 Java 시스템이 모든 스레드를 일시 중단하고 사용하지 않는 개체를 삭제합니다."

"하지만 이 접근 방식은 이제 포기되었습니다. 차세대 가비지 수집기는 배후에서 별도의 스레드에서 작동합니다. 이를 동시 가비지 수집이라고 합니다."

"그렇군요. 개체 삭제 여부는 정확히 어떻게 결정되는 겁니까?"

"객체에 대한 참조 수를 세는 것만으로는 그다지 효과적이지 않습니다. 서로를 참조하는 객체가 있을 수 있지만 다른 객체는 참조하지 않습니다."

"그래서 Java는 다른 접근 방식을 취합니다.  Java는 객체를 도달 가능한 객체와 도달 불가능한 객체로 나눕니다.  객체는 다른 도달 가능한(살아 있는) 객체가 참조하는 경우 도달 가능한(활성) 것입니다. 도달 가능성은 스레드에서 결정됩니다. 실행 중인 스레드는 항상 도달 가능한(활성) 것으로 간주됩니다. , 아무도 언급하지 않더라도."

"좋아. 알 것 같아."

"불필요한 객체를 삭제하는 실제 가비지 수집은 어떻게 이루어지나요?"

"간단합니다. Java에서 메모리는 관례에 따라 두 부분으로 나뉘며 가비지 수집 시간이 되면 모든 살아 있는(도달할 수 있는) 개체가 메모리의 다른 부분으로 복사되고 이전 메모리는 모두 해제됩니다."

"흥미로운 접근 방식입니다. 참조를 세지 않아도 됩니다. 도달 가능한 모든 개체를 복사하고 나머지는 모두 쓰레기입니다."

"그것보다 조금 더 복잡합니다. Java 프로그래머는 객체가 일반적으로 두 가지 범주로 나뉜다는 것을 발견했습니다. 수명이 긴(프로그램이 실행되는 전체 시간 동안 존재) 수명이 짧은(메서드에서 필요하고 «로컬을 수행하는 데 필요함) » 작업)."

"장수 개체를 수명이 짧은 개체와 분리하여 유지하는 것이 훨씬 더 효율적입니다. 이를 위해서는 개체의 수명을 결정하는 방법을 마련해야 했습니다."

"그래서 모든 메모리를 «세대»로 나누었습니다. 1세대 객체, 2세대 객체 등이 있습니다. 메모리가 비워질 때마다 생성 카운터가 1씩 증가합니다. 특정 객체가 여러 세대에 존재하면 수명이 긴 것으로 기록됩니다."

"오늘날 가비지 컬렉터는 Java의 매우 복잡하고 효율적인 부분입니다. 많은 부분이 추측하는 알고리즘을 기반으로 휴리스틱 방식으로 작동합니다. 그 결과 사용자의 말을 듣지 않는 경우가 많습니다."

"의미?"

"Java에는 System.gc () 메서드를 사용하여 호출할 수 있는 가비지 수집기( GC ) 개체가 있습니다 ."

"또한 System.runFinalization()을 사용하여 삭제할 개체의 finalize 메서드를 강제로 호출할 수 있습니다. 그러나 사실 Java 설명서에 따르면 이것은 가비지 수집이 시작되거나 finalize ( ) 메서드가 호출됩니다.  가비지 수집기는 언제 호출할지, 무엇을 호출할지 결정합니다. "

"우와! 알아줘서 반가워."

"그러나 더 많은 것이 있습니다. 아시다시피 Java에서 일부 개체는 다른 개체를 참조합니다. 이 참조 네트워크는 개체를 삭제해야 하는지 여부를 결정하는 데 사용됩니다."

"그리고 보세요. Java에는 이 프로세스에 영향을 줄 수 있는 특수 참조가 있습니다. 특수 래퍼 클래스가 있습니다. 다음은 다음과 같습니다."

" SoftReference  는 소프트 참조입니다."

" WeakReference  는 약한 참조입니다."

" PhantomReference 는 팬텀 참조입니다."

"어... 이건 내부 클래스, 중첩 클래스, 중첩 익명 클래스, 로컬 클래스가 생각나네요. 이름은 다르지만 무엇을 위한 것인지 명확하지 않습니다."

"말해봐, 아미고, 당신은 프로그래머가 되었다. 이제 당신은 클래스 이름 때문에 화를 내며 말하기를 "그것들은 정보가 충분하지 않고, 하나의 이름(!)으로 이 클래스가 무엇을 하는지, 어떻게, 그리고 왜"."

"와우. 눈치채지도 못했는데. 너무 뻔하잖아."

"알겠습니다. 충분합니다. SoftReferences에 대해 말씀드리겠습니다."

"이러한 참조는 캐싱을 위해 특별히 설계되었지만 프로그래머의 재량에 따라 다른 목적으로 사용될 수 있습니다."

"다음은 이러한 참조의 예입니다."

// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"객체에 대한 유일한 참조가 소프트인 경우 계속해서 작동하며 '부드럽게 도달할 수 있음'이라고 합니다."

"그러나!  프로그램에 메모리가 충분하지 않으면 소프트 참조로만 참조되는 객체는 가비지 수집기에 의해 삭제될 수 있습니다.  갑자기 프로그램에 메모리가 충분하지 않으면 OutOfMemoryException 을 발생시키기 전에 가비지 수집기가 모든 객체를 삭제합니다. 소프트 참조에 의해 참조되고 프로그램에 메모리 할당을 다시 시도합니다."

"클라이언트 프로그램이 서버 프로그램에서 다양한 데이터를 자주 요청한다고 가정합니다. 서버 프로그램은 SoftReference를 사용하여 중 일부를 캐시할 수 있습니다. 소프트 참조에 의해 소멸되지 않은 객체가 메모리의 많은 부분을 차지하면 가비지 수집기가 간단히 삭제합니다. 다. 아름다워!"

"그래. 나도 좋아했어."

"음, 한 가지 작은 추가 사항이 있습니다. SoftReference 클래스에는 두 가지 메서드가 있습니다. get() 메서드는 SoftReference에서 참조하는 개체를 반환합니다 . 개체가 가비지 수집기에 의해 삭제된 경우 get ( ) 메서드가 갑자기 null을 반환하기 시작합니다."

"또한 사용자는 clear() 메서드를 호출하여 명시적으로 SoftReference를 지울 수 있습니다 . 이 경우 SoftReference 개체 내부의 약한 링크가 파괴됩니다."

"지금은 여기까지입니다."

"흥미로운 이야기 고마워요, Ellie. 정말 재미있었어요."