Android의 가비지 수집기


108

일부 상황에서 가비지 수집기 호출을 제안하는 많은 Android 답변을 보았습니다.

메모리를 많이 사용하는 작업을 수행하기 전에 Android에서 가비지 수집기를 요청하는 것이 좋은 방법인가요? 그렇지 않은 경우 OutOfMemory오류가 발생한 경우에만 호출해야 합니까?

가비지 컬렉터를 사용하기 전에 사용해야 할 다른 것이 있습니까?

답변:


144

이전 버전의 3.0 벌집 : 예, 전화를 할 System.gc() .

비트 맵을 만들려고했지만 항상 "VM 메모리 부족 오류"가 발생했습니다. 하지만 System.gc()처음 전화했을 때는 괜찮 았습니다.

비트 맵을 만들 때 Android는 종종 메모리 부족 오류로 실패 하고 먼저 가비지 수집을 시도하지 않습니다 . 따라서을 호출 System.gc()하면 비트 맵을 만들 수있는 충분한 메모리가 있습니다.

객체를 생성하는 System.gc경우 필요한 경우 자동으로 호출되지만 비트 맵 생성 에는 호출 되지 않습니다 . 그냥 실패합니다.

따라서 System.gc()비트 맵을 만들기 전에 수동으로 호출하는 것이 좋습니다 .


39
이는 벌집 이전, 비트 맵 데이터가 VM에 저장되지 않아 GC를 트리거하지 않기 때문입니다. Honeycomb 이상에서는 문제가되지 않습니다.
Timmmm

2
@Timmmm 그러나 실제로 내 문제였습니다 .largeheap을 true로 설정했습니다.
Lei Leyba

118

일반적으로 가비지 수집기가있는 경우 수동으로 GC를 호출하는 것은 좋은 습관 이 아닙니다 . GC는 휴리스틱 알고리즘을 중심으로 구성되어 있으며 자신의 장치에 맡길 때 가장 잘 작동합니다. GC를 수동으로 호출하면 종종 성능이 저하됩니다.

때때로 비교적 드문 상황에서 특정 GC가 잘못 이해하고 GC를 수동으로 호출하면 성능 측면에서 개선 될 수 있습니다. 모든 경우에 메모리를 최적으로 관리하는 "완벽한"GC를 구현하는 것이 실제로 불가능하기 때문입니다. 이러한 상황은 예측하기 어렵고 많은 미묘한 구현 세부 사항에 의존합니다. "좋은 방법"은 GC가 자체적으로 실행되도록하는 것입니다. GC에 대한 수동 호출은 예외이며 실제 성능 문제가 정당하게 목격 된 후에 만 ​​계획되어야합니다.


8
좋은 플랫폼 독립적 인 답변은 +1입니다. 선택하기 전에 누군가가 Android 관련 답변을 제시하는지 확인하기를 기다립니다.
hpique

8
"성능"이 CPU 효율성보다 더 일반적인 것을 의미하도록 허용 한다면 귀하가 작성한 내용에 동의합니다 . Android 기기에서는 성능에 대한 사용자의 인식이 가장 중요합니다. 예를 들어 개발자는 사용자가 버튼을 누르고있는 동안 GC를 실행하는 것을 선호 할 수 있으므로 사용자는 GC를 인식하지 못합니다.
James K. Polk 회장

5
게임이 실행되는 동안 GC가 실행되지 않는 것이 게임에서 종종 중요하지만 (모든 개체가 미리 생성되고 재활용되거나 유사해야 함) 게임이 일시 중지되면 GC에 좋은시기입니다.
Pat

4
벌집 이전, 비트 맵 데이터는 VM 메모리에 저장되지 않습니다. 시스템은 비트 맵으로 인해 VM이 아닌 메모리를 너무 많이 사용한 경우를 감지하지 못하고 GC를 실행합니다 ( Bitmap.finalize()VM이 아닌 메모리를 해제하는 방법을 실행 함 ). 따라서이 경우에는, 당신은 해야 GC의의 머리와 실행 가서 Bitmap.recycle()또는 System.gc()적절한를. 그러나 사전 벌집 만.
Timmmm

1
@ThomasPornin-반면에 응용 프로그램 프로그래머는 OS가 알지 못하는 것을 알고 있습니다. 이제 앱이 메모리를 사용하는 방식에 큰 변화주게 될 때사용자 경험은 미래의 임의의 시간보다 지금 잠시 멈춰야합니다 . 즉 , 앱 사용 방식의 주요 전환자주 호출 하지 않는 것이 합리적 일 수 있습니다 . 이는 GC를 자주 호출해서는 안된다는 점에서 드물지만 거의 모든 중요한 앱에 이러한 디자인 별 순간이 있다는 점에서 일반적 입니다.
ToolmakerSteve

26

안드로이드 애플리케이션의 메모리 부족은 비트 맵을 제대로 처리하지 않으면 매우 일반적입니다. 문제에 대한 해결책은 다음과 같습니다.

if(imageBitmap != null) {
    imageBitmap.recycle();
    imageBitmap = null;
}
System.gc();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
imageBitmap = BitmapFactory.decodeFile(URI, options);
Bitmap  scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, 200, 200, true);
imageView.setImageBitmap(scaledBitmap);

위의 코드에서 방금 사용한 메모리 공간을 확보 할 수있는 비트 맵을 재활용하려고했기 때문에 메모리 부족이 발생하지 않을 수 있습니다.

여전히 문제가 발생하면 다음 줄을 추가 할 수도 있습니다.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;

자세한 내용은이 링크를 참조하십시오.

https://web.archive.org/web/20140514092802/http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html?cat=59


참고 : gc 수행으로 인한 일시적인 "일시 중지"로 인해 비트 맵 할당 전에이 작업을 수행하지 않는 것이 좋습니다 .

최적의 설계는 다음과 같습니다.

  1. 무료 더 이상 필요하지 않은 모든 비트 맵 에 의해, if / recycle / null표시 코드를. (그것을 도울 방법을 만드십시오.)

  2. System.gc();

  3. 새 비트 맵을 할당하십시오.


19

OutOfMemoryError가 발생하면 일반적으로 가비지 수집기를 호출하기에는 너무 늦습니다.

다음은 Android 개발자의 인용문입니다.

대부분의 경우 가비지 수집은 수명이 짧은 수많은 개체로 인해 발생하며 세대 별 가비지 수집기와 같은 일부 가비지 수집기는 이러한 개체의 수집을 최적화하여 응용 프로그램이 너무 자주 중단되지 않도록 할 수 있습니다. 안타깝게도 Android 가비지 수집기는 이러한 최적화를 수행 할 수 없으며 성능이 중요한 코드 경로에서 수명이 짧은 객체를 생성하는 것은 애플리케이션에 매우 많은 비용이 듭니다.

그래서 내 이해로는 gc에 긴급히 전화 할 필요가 없습니다. 불필요한 객체 생성 (예 : 루프 내부의 객체 생성)을 피하는 데 더 많은 노력을 기울이는 것이 좋습니다.


6
인용문을 다른 방식으로 해석 할 수 없습니까? 너무 많은 메모리를 사용하기 전에 이러한 개체를 수집하기 위해 GC를 수동으로 호출해야 할 수도 있습니다.
hpique 2010-06-25

@hgpc : 인용문이 당신이 제안한 방식으로 해석 될 수 있는지 모르겠습니다. 나는 그 문서가 그들의 GC가 간단하다는 것을 인정하는 고백이라고 생각한다. 메모리가 부족하면 전체 GC가 실행됩니다.
James K. Polk 회장

복잡한 객체를 최대한 활용하고 복잡한 객체를 사용하는 프레임 워크를 만드는 것은 조기 최적화보다 개발 시간을 더 잘 활용하는 경향이 있습니다. 최적화에 대한 걱정은 우리가 모바일 앱을 코딩하는 동안 무의식적으로 성능에 대해 계속 생각하기 때문에 Enterprise Java보다 Android에서 더 쉬운 함정입니다. 특히 성능에 대해 생각 해야하는 프레임 워크 개발자 는주의하지 않으면 그 관점을 공식 문서에 유출합니다.
LateralFractal

9

System.gc()Art Android 6.0.1 Nexus 5x에서 작동하지 않는 것 같아서 Runtime.getRuntime().gc();대신 사용 합니다.


1
System.gc()에 대한 래퍼 함수입니다 Runtime.getRuntime().gc(). android.googlesource.com/platform/libcore/+/…
Nathan F.

예, 소스와 문서에서 똑같은 것처럼 보이지만 실제로 System.gc()는 작동하지 않지만 작동합니다 Runtime.getRuntime().gc()!
Ivan

7

내 앱은 많은 이미지를 관리하고 OutOfMemoryError로 사망했습니다. 이것은 나를 도왔다. Manifest.xml에서 추가

<application
....
   android:largeHeap="true"> 


1
@PedroPauloAmorim이 이유를 설명합니까?
Machado

2
무엇을하고 있는지 확실하지 않으면 largeHeap을 사용하지 마십시오. 대용량 힙을 사용하면 메모리를 지우기 전에 많은 정크 데이터를 반복해야하므로 가비지 수집기가 훨씬 더 열심히 작동합니다.
Prakash

7

일반적으로 System.gc ()를 사용하여 GC를 명시 적으로 호출해서는 안됩니다. IO 강의 ( http://www.youtube.com/watch?v=_CruQY55HOk )에서도 GC 일시 중지 로그의 의미와 Dalvik이 더 잘 알고 있기 때문에 System.gc ()를 호출하지 말라고 명시하는 내용도 있습니다. 그렇게 할 때보 다.

반면 위의 답변에서 언급했듯이 이미 Android의 GC 프로세스 (다른 모든 것과 마찬가지로)는 때때로 버그가 있습니다. 이것은 Dalvik GC 알고리즘이 Hotspot 또는 JRockit JVM과 동등하지 않으며 경우에 따라 문제가 발생할 수 있음을 의미합니다. 이러한 경우 중 하나는 비트 맵 객체를 할당 할 때입니다. 이것은 Heap 및 Non Heap 메모리를 사용하고 메모리가 제한된 장치에있는 비트 맵 개체의 느슨한 인스턴스 하나가 OutOfMemory 예외를 제공하기에 충분하기 때문에 까다로운 것입니다. 따라서이 비트 맵이 더 이상 필요하지 않은 후에 호출하는 것은 일반적으로 많은 개발자가 제안하고 일부 사람들에게는 좋은 습관으로 간주되기도합니다.

더 나은 방법은 비트 맵의 ​​기본 메모리를 삭제해도 안전한 것으로 표시하기 때문에이 메서드가 만들어진 것처럼 비트 맵에서 .recycle ()을 사용하는 것입니다. 이는 버전에 따라 매우 다르므로 일반적으로 이전 Android 버전 (내 생각에 3.0 이전 버전)에서는 필요하지만 이후 버전에서는 필요하지 않습니다. 또한 최신 버전의 ether에서 사용하는 데 큰 영향을 미치지 않습니다 (루프 또는 이와 유사한 방식으로 수행하지 마십시오). 새로운 ART 런타임은 큰 개체에 대한 특수 힙 "파티션"을 도입했기 때문에 여기에서 많이 변경되었지만 ART 에테르로이 작업을 수행하는 것이 크게 아프지 않을 것이라고 생각합니다.

또한 System.gc ()에 대한 매우 중요한 참고 사항입니다. 이 방법은 Dalvik (또는 JVM)이 응답해야하는 명령이 아닙니다. 가상 머신에 "번거롭지 않은 경우 가비지 수집을 수행 할 수 있습니까?"라고 말하는 것과 비슷합니다.



3

RAM 사용 상태 대한 개발자 문서가 있기 때문에 아니오라고 말할 것입니다 .

...
GC_EXPLICIT

전화 할 때와 같은 명시 적 GC GC () ( 당신이해야 호출 하는 대신 필요할 때 실행할 수있는 GC 신뢰를).

...

관련 부분을 굵게 강조했습니다.

YouTube 시리즈, Android 성능 패턴 을 살펴보세요. 앱의 메모리 사용량을 관리하는 방법 (예 : s 대신 Android ArrayMaps 및 SparseArrays 사용 HashMap)을 보여줍니다.


3

Xamarin 개발자를 위한 빠른 참고 .

당신이 전화를하려는 경우 System.gc()Xamarin.Android 당신이 호출해야 애플 리케이션Java.Lang.JavaSystem.Gc()


2

뒤에 가비지 수집기를 호출 할 필요가 없습니다 OutOfMemoryError.

Javadoc은 다음과 같이 명확하게 설명합니다.

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

따라서 가비지 수집기는 오류를 생성하기 전에 이미 메모리를 확보하려고했지만 실패했습니다.


8
Android Javadoc은이를 명시하지 않으며 구현이 다를 가능성이 높습니다. d.android.com/reference/java/lang/OutOfMemoryError.html
hpique

이것이 Android에 적용되지 않는다는 것이 맞습니다. 그러나 다시 런타임 에테르에서 OOE를 처리 할 수 ​​없으므로 이것이 사실이거나 사실이 아니더라도 그것에 대해 많은 것을 할 수 없습니다.
Igor Čordaš
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.