Programing

Android의 가비지 수집기

lottogame 2020. 8. 12. 22:10
반응형

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;

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

http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html


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

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

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

  2. System.gc();

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


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

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

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

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


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

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

It seems System.gc() do not work on Art Android 6.0.1 Nexus 5x, So I use Runtime.getRuntime().gc(); instead.


Generally speaking you should not call GC explicitly with System.gc(). There is even the IO lecture (http://www.youtube.com/watch?v=_CruQY55HOk) where they explain what the GC pauses log mean and in which they also state to never call System.gc() because Dalvik knows better than you when to do so.

On the other hand as mentioned in above answers already GC process in Android (like everything else) is sometimes buggy. This means Dalvik GC algorithms are not on par with Hotspot or JRockit JVMs and might get things wrong on some occasions. One of those occasions is when allocating bitmap objects. This is a tricky one because it uses Heap and Non Heap memory and because one loose instance of bitmap object on memory constrained device is enough to give you an OutOfMemory exception. So calling it after you don't need this bitmap any-more is generally suggested by many developers and is even considered good practice by some people.

Better practice is using .recycle() on a bitmap as it is what this method is made for, as it marks native memory of the bitmap as safe to delete. Keep in mind that this is very version dependent, meaning it will generally be required on older Android versions (Pre 3.0 I think) but will not be required on later ones. Also it won't hurt much using it on newer versions ether (just don't do this in a loop or something like that). New ART runtime changed a lot here because they introduced special Heap "partition" for big objects but I think it will not hurt much to do this with ART ether.

Also one very important note about System.gc(). This method is not a command that Dalvik (or JVMs) are obligated to respond to. Consider it more like saying to Virtual machine "Could you please do garbage collection if it's not a hassle".


Best way to avoid OOM during Bitmap creation,

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


Quick note for Xamarin developers.

If you would like to call System.gc() in Xamarin.Android apps you should call Java.Lang.JavaSystem.Gc()


There is no need to call the garbage collector after an OutOfMemoryError.

It's Javadoc clearly states:

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.

So, the garbage collector already tried to free up memory before generating the error but was unsuccessful.


I would say no, because the Developer docs on RAM usage state:

...
GC_EXPLICIT

An explicit GC, such as when you call gc() (which you should avoid calling and instead trust the GC to run when needed).

...

I've highlighted the relevant part in bold.

Have a look at the YouTube series, Android Performance Patterns - it will show you tips on managing your app's memory usage (such as using Android's ArrayMaps and SparseArrays instead of HashMaps).

참고URL : https://stackoverflow.com/questions/3117429/garbage-collector-in-android

반응형