[java] Android의 가비지 수집기

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

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

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



답변

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

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

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

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

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


답변

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

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


답변

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

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. 새 비트 맵을 할당하십시오.


답변

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

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

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

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


답변

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


답변

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

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


답변

일반적으로 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)이 응답해야하는 명령이 아닙니다. 가상 머신에 “번거롭지 않은 경우 가비지 수집을 수행 할 수 있습니까?”라고 말하는 것과 비슷합니다.