2011-04-22 6 views
10

Android 애플리케이션의 캐싱 메커니즘을 구현하는 중입니다.SoftReference가 가비지 수집을 너무 일찍 시작합니다.

내가 찾은 많은 사례처럼 SoftReference을 사용합니다. 문제는 내 ListView에서 위 또는 아래로 스크롤 할 때 이미지가 인 경우 이 이미 삭제 된 것입니다. LogCat에서 응용 프로그램이 새 이미지를로드 할 때마다 내 응용 프로그램이 가비지 수집됨을 알 수 있습니다. 이는 ListView에있는 보이지 않는 이미지 중 이 대부분이 사라짐을 의미합니다.

그래서, 나는 다시 한 번 이미지를 다운로드해야합니다 (전에 정말 이미지를 다운로드) 이전 위치로 매번 내가 스크롤 다시 - 그들은 있어를 캐시되지 않습니다.

이 주제를 연구했습니다. According to Mark Murphy in this article, SoftReference 버그가있는 것 같습니다 (또는 있었습니까?). 다른 결과는 같은 것을 나타냅니다 (또는 같은 결과). SoftReference가 너무 일찍 삭제됩니다.

작동하는 해결책이 있습니까?

+2

** 너무 일찍 **? 메모리가 필요하면 지워집니다. 누가 너무 일찍 말 할까? 시스템이 그것을 지우고 싶다면, 이것은 softreference가 무엇인지에 대한 것입니다. – binnyb

+0

정확함. 하지만 메모리에 50 개의 이미지를 쉽게 저장할 수 있기 때문에 더 많은 메모리가 필요하지 않습니다. 하지만 OOM 오류를 피하기 위해이 캐싱 메커니즘을 사용해야합니다. – Wroclai

+0

캐시에서 각 이미지를 캐시하는 것이 좋습니다. 캐시에서 데이터를 가져올 필요가 없습니다 (캐시에없는 경우 제외). – binnyb

답변

16

SoftReference는 캐시 가난한 사람입니다. JVM은 이러한 참조를 오래 유지할 수는 있지만 꼭 그렇게 할 필요는 없습니다. 더 이상 하드 참조가 없으면 JVM은 소프트 참조 객체를 가비지 수집 할 수 있습니다. JVM이 그러한 객체를 오래 보관할 필요가 없기 때문에 발생한 JVM의 동작이 정확합니다. 물론 대부분의 JVM은 소프트 참조 객체를 어느 정도 유지하려고합니다.

따라서 SoftReferences는 일종의 위험한 캐시입니다. 정말로 캐싱 동작을 보장하려면 실제 캐쉬가 필요합니다. LRU-cache처럼 특히 성능이 중요한 캐싱이라면 적절한 캐시를 사용해야합니다.

+0

명확한 답변! 감사! LRU 캐시를 살펴보고 내가 원하는 것인지 확인합니다. 하지만 JVM이 "더 이상"부드러운 참조를 보유하지 않는 이유는 무엇입니까? 실제로 메모리가 남아 있습니다 ... – Wroclai

+3

그것은 필요가 없기 때문입니다. SR 계약에 대한 이해가 잘못되었습니다. GC는 응용 프로그램의 성능에 영향을 미치지 않고 간단히 수행 할 시간이 없기 때문에 SR을 OOM 순간까지 연기하는 것을 "원하지"않습니다. –

+0

@road to yamburg : 삭제 해 주셔서 감사합니다! – Wroclai

2

각 이미지를 메모리가 아닌 영구 저장 장치에 캐시하십시오.

+0

임시 캐시의 영구 저장소? 권리. 이것은 해결책입니다. 다른 문제. –

+0

일시적인 캐시가 필요하다는 것은 명확하지 않습니다. –

1

Gamlor의 답변은 귀하의 지역에서 정확합니다. 그러나, 자세한 내용은 GC FAQ을 볼 여유 공간이 나머지를 계산합니다 (-Xmx 옵션으로 설정 한) 자바 핫스팟 서버 VM이 가능한 최대 힙 크기를 사용하여 32

질문.

Java HotSpot 클라이언트 VM은 현재 힙 크기를 사용하여 여유 공간을 계산합니다.

이것은 서버 VM이 소프트 참조를 플러시하는 것이 아니라 힙을 늘리는 것이 일반적이므로 -Xmx는 소프트 참조가 가비지 수집 될 때 중요한 영향을 미친다는 것을 의미합니다. 안드로이드 교육 사이트에서

+1

JVM에서는 안드로이드 애플리케이션이 실행되지 않습니다. – Jan

+0

안드로이드는 적어도 조금은 소프트 레퍼런스를 유지할 것이지만 SoftReference를 사용하여 데이터가 사라지면 즉시 삭제할 수 있다는 사실을 염두에 두어야한다는 사실을 감안해야합니다. JVM이 올바르게 처리합니다. Android는 기본적으로 가비지 수집기로 할 수있는 모든 것을 먹습니다. 그래서 JVM FAQ는 위의 문제보다 무의미합니다. 그 대답은 기본적으로 강력한 참조를 사용합니다. – Tatarize

7

: 과거

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

하는 인기있는 메모리 캐시 구현은 또는 WeakReference를 비트 맵 캐시 그러나이 권장되지 않는하는 SoftReference이었다. Android 2부터 시작합니다.3 (API 레벨 9) 가비지 컬렉터는 더 부드럽고 약한 참조를 수집하여 공격적으로 입니다. 매우 효과적입니다. 또한 Android 3.0 (API 레벨 11) 이전에는 비트 맵의 ​​백업 데이터가 예상치 못한 방식으로 해제 된 이 아닌 기본 메모리에 저장되어 응용 프로그램 이 일시적으로 메모리 제한을 초과하여 충돌을 일으킬 수 있습니다.

자세한 정보가 링크에 포함되어 있습니다.

우리는 대신 LruCache을 사용합니다.

+0

감사! 나는 다음 번에 그것을 고려할 것이다! – Wroclai

관련 문제