Programing

프로젝트에서 PhantomReference를 사용한 적이 있습니까?

lottogame 2020. 10. 6. 07:43
반응형

프로젝트에서 PhantomReference를 사용한 적이 있습니까?


내가 아는 유일한 것은 약 PhantomReference이다

  • get()메서드 를 사용 하면 항상 null개체가 아닌 반환됩니다 . 그것의 용도는 무엇입니까?
  • 를 사용하여 메서드 PhantomReference에서 개체를 부활시킬 수 없음을 확인합니다 finalize.

그러나이 개념 / 클래스의 용도는 무엇입니까?

프로젝트에서 이것을 사용한 적이 있습니까? 아니면 우리가 이것을 사용해야 할 예가 있습니까?


객체 생성 및 파괴를 모니터링하기 위해 단순하고 매우 특수한 종류의 메모리 프로파일 러PhantomReference 에서 s를 사용했습니다 . 파괴를 추적하기 위해 그것들이 필요했습니다. 그러나 접근 방식은 구식입니다. (J2SE 1.4를 대상으로 2004 년에 작성되었습니다.) 전문 프로파일 링 도구는 훨씬 더 강력하고 안정적이며 JMX 또는 에이전트 및 JVMTI와 같은 최신 Java 5 기능도이를 위해 사용할 수 있습니다.

PhantomReferences (항상 참조 대기열과 함께 사용됨) finalize는 몇 가지 문제가 있으므로 피해야하는 것 보다 우수합니다 . 주로 개체에 다시 도달 할 수 있도록합니다. 이것은 종료 자 가디언 관용구 (-> 'Effective Java'에서 더 많은 것을 읽으십시오)로 피할 수 있습니다. 그래서 그들은 또한 새로운 finalize 입니다.

또한 PhantomReferences

개체가 메모리에서 제거 된시기를 정확히 확인할 수 있습니다. 사실 그들은 그것을 결정하는 유일한 방법입니다. 이것은 일반적으로 그다지 유용하지 않지만 큰 이미지 조작과 같은 특정 상황에서 유용 할 수 있습니다. 이미지가 가비지 수집되어야 함을 확실히 알고 있다면 다음 이미지를로드하기 전에 실제로 될 때까지 기다릴 수 있습니다. , 따라서 두려운 OutOfMemoryError의 가능성을 줄입니다. ( enicholas 에서 인용 .)

그리고 psd 가 먼저 썼 듯이 Roedy Green은 참고 문헌을 잘 요약했습니다 .


Java Glossary 일반적인 요약 테이블 설명 입니다.

와 코스 일치의 어떤 PhantomReference 문서 :

수집기가 참조 대상을 회수 할 수 있다고 결정한 후 대기열에 추가되는 팬텀 참조 개체입니다. Phantom 참조는 Java 종료 메커니즘에서 가능한 것보다 더 유연한 방식으로 사전 정리 조치를 스케줄링하는 데 가장 자주 사용됩니다.

그리고 마지막으로 모든 세부 사항 ( 좋은 읽기 ) : Java Reference Objects (또는 How I Learned to Stop Worrying and Love OutOfMemoryError) .

즐거운 코딩입니다. (그러나 질문에 답하기 위해 WeakReferences 만 사용했습니다.)


팬텀 레퍼런스 사용법에 대한 훌륭한 설명 :

가상 참조는 객체가 메모리에서 제거되었음을 알 수있는 안전한 방법입니다. 예를 들어, 큰 이미지를 처리하는 애플리케이션을 고려하십시오. 가비지 수집을 위해 준비된 큰 이미지가 이미 메모리에있을 때 큰 이미지를 메모리에로드한다고 가정합니다. 이 경우 새 이미지를로드하기 전에 이전 이미지가 수집 될 때까지 기다려야합니다. 여기에서 가상 참조는 유연하고 안전하게 선택할 수있는 옵션입니다. 이전 이미지 개체가 완료되면 이전 이미지의 참조가 ReferenceQueue에 추가됩니다. 해당 참조를받은 후 새 이미지를 메모리에로드 할 수 있습니다.


나는의 실용적이고 유용한 사용 사례 발견 PhantomReference되는 org.apache.commons.io.FileCleaningTracker공유지-IO 프로젝트를. FileCleaningTracker마커 개체가 가비지 수집되면 실제 파일을 삭제합니다.
주목할 점은 Tracker클래스를 확장하는 PhantomReference클래스입니다.


이것은 JAVA 9에서 더 이상 사용되지 않아야합니다! 대신
사용하십시오 java.util.Cleaner! (또는 sun.misc.Cleaner이전 JRE에서)

원본 게시물 :


나는 PhantomReferences의 사용이 종료 자 메서드와 거의 같은 양의 함정을 가지고 있다는 것을 발견했습니다 (하지만 제대로 된 후에는 문제가 적습니다). Java 8 용 작은 솔루션 (PhantomReferences를 사용하기위한 매우 작은 프레임 워크)을 작성했습니다. 객체가 제거 된 후 실행할 콜백으로 람다 식을 사용할 수 있습니다. 닫아야하는 내부 리소스에 대한 콜백을 등록 할 수 있습니다. 이것으로 훨씬 더 실용적이기 때문에 저에게 맞는 솔루션을 찾았습니다.

https://github.com/claudemartin/java-cleanup

다음은 콜백 등록 방법을 보여주는 간단한 예입니다.

  class Foo implements Cleanup {
    //...  
    public Foo() { 
    //...    
      this.registerCleanup((value) -> {
        try {
          // 'value' is 'this.resource'
          value.close();
        } catch (Exception e) {
          logger.warning("closing resource failed", e);
        }
      }, this.resource);
    }

그리고 위와 거의 동일한 자동 닫기 방법이 있습니다.

this.registerAutoClose(this.resource);

질문에 답하려면 :

[그런 다음 그것의 사용은 무엇입니까]

존재하지 않는 것을 정리할 수 없습니다. 그러나 여전히 존재하고 제거 할 수 있도록 정리해야하는 리소스가있을 수 있습니다.

그러나이 개념 / 클래스의 용도는 무엇입니까?

디버깅 / 로깅 이외의 다른 효과로 반드시 수행 할 필요는 없습니다. 아니면 통계를 위해. GC의 알림 서비스처럼 보입니다. 개체가 제거되면 관련성이없는 집계 데이터를 제거하는 데 사용할 수도 있습니다 (하지만 더 나은 솔루션이있을 수 있음). 예제에서는 종종 데이터베이스 연결을 닫아야한다고 언급하지만 트랜잭션 작업을 할 수 없기 때문에 이것이 얼마나 좋은 생각인지 모르겠습니다. 애플리케이션 프레임 워크는이를위한 훨씬 더 나은 솔루션을 제공합니다.

당신의 프로젝트에서 이것을 사용한 적이 있습니까, 아니면 우리가 이것을 사용해야 할 예가 있습니까? 아니면이 개념은 인터뷰 관점에서 만 만들어진 것입니까?)

나는 주로 로깅에만 사용합니다. 따라서 제거 된 요소를 추적하고 GC가 어떻게 작동하고 조정할 수 있는지 확인할 수 있습니다. 나는 이런 식으로 중요한 코드를 실행하지 않을 것입니다. 무언가를 닫아야하는 경우 try-with-resource-statement에서 수행해야합니다. 그리고 메모리 누수가 없는지 확인하기 위해 단위 테스트에서 사용합니다. jontejj와 같은 방식으로합니다. 하지만 내 솔루션은 좀 더 일반적입니다.


단위 테스트에서 PhantomReference를 사용하여 테스트중인 코드가 일부 개체에 대한 비 필수 참조를 유지하지 않았는지 확인했습니다. ( 원래 코드 )

import static com.google.common.base.Preconditions.checkNotNull;
import static org.fest.assertions.Assertions.assertThat;

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

import com.google.common.testing.GcFinalization;

/**
* Helps to test for memory leaks
*/
public final class MemoryTester
{
private MemoryTester()
{
}

/**
* A simple {@link PhantomReference} that can be used to assert that all references to it is
* gone.
*/
public static final class FinalizationAwareObject extends PhantomReference<Object>
{
private final WeakReference<Object> weakReference;

private FinalizationAwareObject(Object referent, ReferenceQueue<Object> referenceQueue)
{
super(checkNotNull(referent), referenceQueue);
weakReference = new WeakReference<Object>(referent, referenceQueue);
}

/**
* Runs a full {@link System#gc() GC} and asserts that the reference has been released
* afterwards
*/
public void assertThatNoMoreReferencesToReferentIsKept()
{
String leakedObjectDescription = String.valueOf(weakReference.get());
GcFinalization.awaitFullGc();
assertThat(isEnqueued()).as("Object: " + leakedObjectDescription + " was leaked").isTrue();
}
}

/**
* Creates a {@link FinalizationAwareObject} that will know if {@code referenceToKeepTrackOff}
* has been garbage collected. Call
* {@link FinalizationAwareObject#assertThatNoMoreReferencesToReferentIsKept()} when you expect
* all references to {@code referenceToKeepTrackOff} be gone.
*/
public static FinalizationAwareObject createFinalizationAwareObject(Object referenceToKeepTrackOff)
{
return new FinalizationAwareObject(referenceToKeepTrackOff, new ReferenceQueue<Object>());
}
}

그리고 테스트 :

@Test
public void testThatHoldingOnToAnObjectIsTreatedAsALeak() throws Exception
{
    Object holdMeTight = new String("Hold-me-tight");
    FinalizationAwareObject finalizationAwareObject = MemoryTester.createFinalizationAwareObject(holdMeTight);
    try
    {
    finalizationAwareObject.assertThatNoMoreReferencesToReferentIsKept();
    fail("holdMeTight was held but memory leak tester did not discover it");
    }
    catch(AssertionError expected)
    {
    assertThat(expected).hasMessage("[Object: Hold-me-tight was leaked] expected:<[tru]e> but was:<[fals]e>");
    }
}

It is common to use WeakReference where PhantomReference is more appropriate. This avoids certain problems of being able to resurrect objects after a WeakReference is cleared/enqueued by the garbage collector. Usually the difference doesn't matter because people are not playing silly buggers.

Using PhantomReference tends to be a bit more intrusive because you can't pretend that the get method works. You can't, for example, write a Phantom[Identity]HashMap.


if you use its get() method it will always return null, and not the object. [ then whats the use of it ]

The useful methods to call (rather than get()) would be isEnqueued() or referenceQueue.remove(). You would call these methods to perform some action that needs to take place on the final round of garbage collection of the object.

The first time around is when the object has its finalize() method called, so you could put closing hooks there too. However, as others have stated, there are probably more sure ways of performing clean up or whatever action needs to take place pre and post garbage collection or, more generally, upon end-of-life of the object.

참고URL : https://stackoverflow.com/questions/1599069/have-you-ever-used-phantomreference-in-any-project

반응형