자바 가 어떻게 자원 회수 보완 을 하 는 지 에 대해 논 하 다.
최종 화 회수
finalize 방식 은 자바 대상 이 회수 되 었 을 때 발생 하 는 방법 입 니 다.자바 의 많은 자원 대상 은 finalize 에 담보 방법 을 썼 습 니 다.
/**
* Ensures that the <code>close</code> method of this file input stream is
* called when there are no more references to it.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if ((fd != null) && (fd != FileDescriptor.in)) {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
위 는 FileInputStream 의 finalize 방법 입 니 다.방법 이 호출 될 때 파일 설명자 가 존재 하 는 지 확인 하고 존재 하면 close 방법 을 사용 합 니 다.자원 의 회 수 를 확보 하 다.finalize 방법 은 우리 가 자바 를 배 울 때 재 작성 하 는 것 을 추천 하지 않 고 복잡 한 논 리 를 쓰 는 것 을 추천 하지 않 습 니 다.주로 gc 를 배 울 때 이 방법 을 사용 하기 때 문 입 니 다.만약 에 실행 하 는 내용 이 너무 많 으 면 gc 가 길 어 집 니 다.프로그램의 정상 적 인 운행 에 영향 을 주다.그리고 여기 도 간단 한 담보 일 뿐 이 야.대부분의 희망 은 코드 를 작성 하 는 사람 이 close 를 호출 할 수 있 습 니 다.이렇게 하면 닫 힌 코드 를 제대로 호출 하지 않 고 판단 할 때 끝난다.
클 리 너 회수
DirectByte Buffer 에 서 는 클 리 너 대상 을 사용 해 보완 했다.
unsafe.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {
// Round up to page boundary
address = base + ps - (base & (ps - 1));
} else {
address = base;
}
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
att = null;
자원 을 신청 하면 Deallocator 대상 을 만 듭 니 다.
private static class Deallocator
implements Runnable
{
private static Unsafe unsafe = Unsafe.getUnsafe();
private long address;
private long size;
private int capacity;
private Deallocator(long address, long size, int capacity) {
assert (address != 0);
this.address = address;
this.size = size;
this.capacity = capacity;
}
public void run() {
if (address == 0) {
// Paranoia
return;
}
unsafe.freeMemory(address);
address = 0;
Bits.unreserveMemory(size, capacity);
}
}
Deallocator 의 run 방법 에서 자원 의 방출 이 진행 되 었 습 니 다.실행 시 기 는 클 리 너 에 의 해 촉발 된다.클 리 너 는 팬 텀 레 퍼 런 스 의 하위 클래스 이 고,팬 텀 레 퍼 런 스 는 레 퍼 런 스 의 하위 클래스 다.
그 중 에 Reference Handler 가 있어 요.
private static class ReferenceHandler extends Thread {
그의 run 방법 은 cleaner 의 clean 방법 을 호출 하 는 것 이다.이 스 레 드 는 정적 블록 에서 작 동 되 었 다.
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
@Override
public boolean tryHandlePendingReference() {
return tryHandlePending(false);
}
});
이와 함께 Shared Secrets 에 자바 랑 RefAccess 를 설정 했다.clean 방법 을 호출 하 는 과정 은 try Handle Pending 에서 중요 합 니 다.
static boolean tryHandlePending(boolean waitForNotify) {
Reference<Object> r;
Cleaner c;
try {
synchronized (lock) {
if (pending != null) {
r = pending;
// 'instanceof' might throw OutOfMemoryError sometimes
// so do this before un-linking 'r' from the 'pending' chain...
c = r instanceof Cleaner ? (Cleaner) r : null;
// unlink 'r' from 'pending' chain
pending = r.discovered;
r.discovered = null;
} else {
// The waiting on the lock may cause an OutOfMemoryError
// because it may try to allocate exception objects.
if (waitForNotify) {
lock.wait();
}
// retry if waited
return waitForNotify;
}
}
} catch (OutOfMemoryError x) {
// Give other threads CPU time so they hopefully drop some live references
// and GC reclaims some space.
// Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above
// persistently throws OOME for some time...
Thread.yield();
// retry
return true;
} catch (InterruptedException x) {
// retry
return true;
}
wait ForNotify 가 true 일 때 회수 대상 이 없 을 때 차단 에 들 어가 서 ooe 를 기다린다.바깥쪽 은 사순환 으로 다시 호출 되 고 다음 에 들 어 올 때 클 린 을 출발 할 수 있 습 니 다.Reference Handler 는 관리 체제 의 일종 이다.
또 하 나 는 Shared Secrets 가 try Handle Pending(false)을 호출 하 는 것 이다.
다른 클래스,bits 에서
final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
// retry while helping enqueue pending Reference objects
// which includes executing pending Cleaner(s) which includes
// Cleaner(s) that free direct buffer memory
while (jlra.tryHandlePendingReference()) {
if (tryReserveMemory(size, cap)) {
return;
}
}
reserve Memory 를 할 때 Shared Secrets 에서 try Handle Pending(false)을 호출 합 니 다.이곳 에 서 는 또 변 형 된 회수 가 진행 되 었 다.작은 매듭
자바 재 활용 두 가지 메커니즘.하 나 는 finalize,하 나 는 Cleaner.그 중에서 클 리 너 일 부 는 oome 에 의존 하여 회 수 를 촉발 하고 일 부 는 reserveMemory 에서 회 수 를 한다.
자바 가 자원 회수 보완 을 어떻게 하 는 지 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 자원 회수 보완 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.