Java의 참조 유형 전체 해석

7063 단어 Java참조 유형
만약 메모리에 있는 대상이 인용이 없다면, 이 대상은 더 이상 사용되지 않고, 쓰레기 회수 후보가 될 수 있다는 것을 의미한다.그러나 쓰레기 수거기의 운행 시간이 불확실하기 때문에 쓰레기 회수 대상의 실제 회수 시간은 불확실하다.하나의 대상에 대해 말하자면, 인용된 존재만 있다면, 그것은 메모리에 계속 존재할 것이다.이러한 객체가 점점 많아지면 JVM의 총 메모리 수를 초과하면 JVM에서 OutOfMemory 오류가 발생합니다.쓰레기 수거의 구체적인 운행은 JVM이 통제하지만 개발자는 어느 정도 쓰레기 수거기와 상호작용을 할 수 있다. 쓰레기 수거기가 응용된 메모리를 잘 관리하도록 돕는 데 목적이 있다.이런 상호작용 방식은 JDK 1.2에서 도입한java를 사용하는 것이다.lang.ref 패키지.
1 강인용
강제 인용은 가장 보편적인 인용을 사용하는 것이다.만약 대상이 강한 인용을 가지고 있다면, 쓰레기 수거기는 절대로 그것을 회수하지 않을 것이다.메모리 공간이 부족하면 자바 가상 컴퓨터는 Out Of Memory Error 오류를 내서 프로그램을 이상하게 종료할지언정 강력한 인용 대상을 임의로 회수해서 메모리 부족 문제를 해결하지 않습니다.
Date date = new Date () 와 같이 date는 객체의 강력한 참조입니다.대상의 강한 인용은 프로그램 곳곳에서 전달될 수 있다.많은 경우, 동시에 여러 개의 인용이 같은 대상을 가리킨다.강제 인용의 존재는 대상이 메모리에서 살아남는 시간을 제한한다.만약 대상 A에 대상 B의 강한 인용이 포함되어 있다면, 일반적인 상황에서 대상 B의 생존 시간은 대상 A보다 짧지 않을 것이다.만약 대상 A가 명시적으로 대상 B의 인용을null로 설정하지 않았다면, 대상 A가 쓰레기로 회수된 후에야 대상 B가 더 이상 인용이 그것을 가리키지 않고 쓰레기로 회수될 기회를 얻을 수 있다.
인스턴스 코드:

package com.skywang.java;

public class StrongReferenceTest {

 public static void main(String[] args) {
  MyDate date = new MyDate();
  System.gc();
 }
}

실행 결과:
<출력 없음>
결과 설명: 쓰레기 회수를 현식으로 호출했더라도,date는 강제 인용이고,date는 회수되지 않았습니다.
강제 인용을 제외하고java.lang.ref 패키지는 한 대상에 대한 다른 인용 방식을 제공합니다.JVM의 쓰레기 수거기는 유형별 참조에 따라 처리 방식이 다릅니다.
2 소프트 참조
만약 대상이 소프트 인용만 가지고 있다면 메모리 공간이 충분하고 쓰레기 회수기는 그것을 회수하지 않을 것이다.메모리 공간이 부족하면 이 대상의 메모리를 회수합니다.쓰레기 수거기가 그것을 회수하지 않으면 그 대상은 프로그램에 의해 사용될 수 있다.소프트 참조는 메모리에 민감한 캐시를 실현하는 데 사용할 수 있다.
소프트 참조는 참조 대기열(ReferenceQueue)과 함께 사용할 수 있습니다. 소프트 참조가 인용된 대상이 쓰레기 수거기에서 회수되면 Java 가상 머신이 이 소프트 참조를 관련 참조 대기열에 추가합니다.
소프트 참조(soft reference)는 강도적으로 강한 참조보다 약하며 클래스 Soft Reference를 통해 표시됩니다.프로그램의 어떤 대상이 중요하지 않고 메모리가 부족할 때 잠시 회수될 수 있는지 알려주는 역할을 한다.JVM의 메모리가 부족하면 스팸 수거기는 소프트 참조로만 가리키는 객체를 방출합니다.이 대상을 모두 방출한 후에 메모리가 부족하면 OutOfMemory 오류가 발생합니다.소프트 참조는 캐시를 만드는 데 매우 적합하다.시스템 메모리가 부족할 때 캐시의 내용은 방출될 수 있습니다.예를 들어 이미지 편집기를 고려하는 프로그램.이 프로그램은 그림 파일의 모든 내용을 메모리에 읽어서 처리하기 쉽도록 합니다.사용자도 여러 파일을 동시에 열 수 있습니다.동시에 열린 파일이 너무 많을 때 메모리 부족을 초래할 수 있습니다.이미지 파일의 내용을 가리키는 플러그인을 사용하면 쓰레기 수거기는 필요할 때 이 메모리를 회수할 수 있다.    
인스턴스 코드:

package com.skywang.java;

import java.lang.ref.SoftReference;

public class SoftReferenceTest {

 public static void main(String[] args) {
  SoftReference ref = new SoftReference(new MyDate());
  ReferenceTest.drainMemory();
 }
}

실행 결과:
<출력 없음>
결과 설명: 메모리가 부족할 때 소프트 참조가 종료됩니다.소프트 인용이 금지되었을 때,

SoftReference ref = new SoftReference(new MyDate());
ReferenceTest.drainMemory();
... 과 같다

MyDate date = new MyDate();

//  JVM 
if(JVM. ()) {
 date = null;
 System.gc();
}

3 약인용
약한 참조(weak reference)는 강도적으로 부드러운 참조보다 약하며, 클래스 Weak Reference를 통해 표시합니다.그것의 역할은 하나의 대상을 인용하는 것이지만, 그 대상이 회수되는 것을 막지는 않는다.만약 강한 인용을 사용한다면, 이 인용이 존재한다면, 인용된 대상은 회수될 수 없습니다.약한 인용은 이 문제가 없다.쓰레기 수거기가 실행될 때 한 대상의 모든 인용이 약한 인용이라면 그 대상은 회수됩니다.약한 인용의 역할은 강한 인용이 가져오는 대상 간의 생존 시간에서의 결합 관계를 해결하는 데 있다.약한 인용의 가장 흔히 볼 수 있는 용도는 집합류, 특히 해시표에 있다.해시 테이블의 인터페이스는 모든 Java 객체를 키로 사용할 수 있습니다.키 값이 해시 테이블에 들어가면 해시 테이블 대상 자체에 키와 값 대상에 대한 인용이 있습니다.만약 이런 인용이 강제 인용이라면, 해시표 대상 자체가 살아남기만 한다면, 그 안에 포함된 키와 값 대상은 회수되지 않을 것이다.만약 생존 시간이 긴 해시 테이블에 포함된 키 값이 매우 많다면 결국 JVM의 모든 메모리를 소모할 수 있다.
이런 상황에 대한 해결 방법은 약인을 사용하여 이 대상을 인용하는 것이다. 이렇게 하면 해시표의 키와 값 대상이 모두 쓰레기로 회수될 수 있다.Java에서는 이러한 일반적인 요구 사항을 충족시키기 위해 WeakHashMap을 제공합니다.
예제 코드:

package com.skywang.java;

import java.lang.ref.WeakReference;

public class WeakReferenceTest {

 public static void main(String[] args) {
  WeakReference ref = new WeakReference(new MyDate());
  System.gc(); 
 }
}

실행 결과:

obj [Date: 1372142034360] is gc
결과 설명: 약참조는 JVM 쓰레기 수거 실행 중에 종료됩니다.

WeakReference ref = new WeakReference(new MyDate());
System.gc();
다음과 같습니다.

MyDate date = new MyDate();

//  
if(JVM. ()) {
 date = null;
 System.gc();
}

약한 인용과 부드러운 인용의 차이는 약한 인용만 있는 대상은 더욱 짧은 생명 주기를 가진다는 데 있다.쓰레기 수거기가 관할하는 메모리 구역을 스캔하는 과정에서 약한 인용만 있는 대상을 발견하면 현재 메모리 공간이 충분하든 그렇지 않든 메모리를 회수합니다.그러나 쓰레기 수거기는 우선순위가 낮은 라인이기 때문에 약한 인용만 있는 대상을 빨리 발견할 수 있는 것은 아니다.
약한 인용은 인용 대기열(ReferenceQueue)과 연합하여 사용할 수 있으며, 약한 인용이 인용된 대상이 쓰레기로 회수되면 자바 가상 머신이 이 약한 인용을 관련된 인용 대기열에 추가합니다.
4 가상 참조
유령 인용이라고도 합니다. 유령 인용을 소개하기 전에 자바가 제공하는 대상 종지화 메커니즘(finalization)을 소개합니다.Object 클래스에finalize 방법이 있는데 그 디자인의 취지는 대상이 진정으로 회수되기 전에 정리 작업을 수행할 수 있다는 것이다.자바는 C++와 같은 분석 함수와 같은 메커니즘을 제공하지 않았기 때문에finalize 방법을 통해 실현되었다.그러나 문제는 쓰레기 수거기의 운행 시간이 고정되지 않기 때문에 이런 청소 작업의 실제 운행 시간도 예측할 수 없다는 점이다.유령 인용 (phantom reference) 은 이 문제를 해결할 수 있습니다.팬텀 참조 PhantomReference를 만들 때 참조 대기열을 지정해야 합니다.대상의finalize 방법이 호출되면 이 대상의 유령 인용은 대기열에 추가됩니다.이 대열의 내용을 검사하면 대상이 회수될 준비가 되어 있는지 알 수 있다.
유령 인용과 그 대기열의 사용 상황은 흔치 않다. 주로 비교적 정교한 메모리 사용 제어를 실현하는 데 사용되는데 이것은 이동 장치에 있어 매우 의미가 있다.프로그램은 대상이 회수될 것을 확인한 후에 메모리로 새로운 대상을 만들 수 있습니다.이런 방식을 통해 프로그램이 소모하는 메모리를 상대적으로 낮은 수량으로 유지할 수 있다.
예를 들어 아래의 코드는 버퍼의 실현 예시를 제시했다.

public class PhantomBuffer {
 private byte[] data = new byte[0];
 private ReferenceQueue<byte[]> queue = new ReferenceQueue<byte[]>();
 private PhantomReference<byte[]> ref = new PhantomReference<byte[]>(data, queue);
 public byte[] get(int size) {
  if (size <= 0) {
   throw new IllegalArgumentException("Wrong buffer size");
  }
  if (data.length < size) {
   data = null;
   System.gc(); // 
    try {
    queue.remove(); // 
    ref.clear(); // , 
    ref = null;
    data = new byte[size];
    ref = new PhantomReference<byte[]>(data, queue);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  return data;
 }
}
위의 코드에서 새로운 버퍼를 신청할 때마다 이전 버퍼의 바이트 그룹이 성공적으로 회수되었는지 확인합니다.인용 대기열의remove 방법은 새로운 유령 인용이 대기열에 추가될 때까지 막힙니다.그러나 주의해야 할 것은 이런 방법은 쓰레기 회수기가 너무 많이 운행되어 프로그램의 흡수량이 너무 낮아질 수 있다는 것이다.
예제 코드:

package com.skywang.java;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.PhantomReference;

public class PhantomReferenceTest {

 public static void main(String[] args) {
  ReferenceQueue queue = new ReferenceQueue();
  PhantomReference ref = new PhantomReference(new MyDate(), queue);
  System.gc();
 }
}

실행 결과:

obj [Date: 1372142282558] is gc
결과 설명: 가짜 인용은 실례화된 후에 중지되었다.

ReferenceQueue queue = new ReferenceQueue();
PhantomReference ref = new PhantomReference(new MyDate(), queue);
System.gc();
다음과 같습니다.

MyDate date = new MyDate();
date = null;

좋은 웹페이지 즐겨찾기