OOM이란?OOM 문제를 해결하는 방법!
9336 단어 코드 경험의 구덩이
1. OOM이란 무엇인가?
프로그램 신청 메모리가 너무 커서 가상 컴퓨터가 우리를 만족시키지 못하고 자살했다.이 현상은 보통 큰 그림의 앱 개발이나 많은 그림이 필요할 때 나타난다.통속적으로 말하면 우리의 APP가 이미지를 저장하기 위해 메모리를 신청해야 할 때 시스템은 우리의 프로그램에 필요한 메모리가 너무 크다고 생각하고 시스템에 충분한 메모리가 있다. 예를 들어 1G이다. 그러나 시스템이 우리의 APP에 분배되지 않기 때문에 OOM 이상을 던지고 프로그램이 이상을 포착하지 않았기 때문에 창문이 무너졌다.
2、왜 OOM이 있나요?
안드로이드 시스템의 APP는 모든 프로세스나 가상 기기에 최대 메모리 제한이 있기 때문에 이 제한을 초과하면 OOM 오류가 발생합니다.핸드폰의 남은 메모리가 충분한지 여부와는 별 상관이 없다.
3. 왜 안드로이드에 앱의 메모리 제한이 있는지
(1) 개발자가 메모리를 사용하는 것이 더욱 합리적이어야 한다.모든 응용 프로그램의 사용 가능한 메모리 상한선을 제한하고 악성 프로그램이나 한 프로그램이 너무 많은 메모리를 사용해서 다른 프로그램이 실행될 수 없도록 합니다.제한이 있으면 개발자는 반드시 자원을 합리적으로 사용하고 자원의 사용을 최적화해야 한다
(2) 화면 표시가 제한되어 메모리가 충분하다.설령 천만 개의 그림과 천만 개의 데이터를 사용해야 한다고 해도 특정한 시간에 사용자에게 보여줄 수 있는 것은 항상 제한적이다. 왜냐하면 화면의 표시가 그렇게 크고 위에 놓을 수 있는 정보는 매우 제한적이기 때문이다.대부분의 정보는 디스플레이 준비 상태이기 때문에 헤프 메모리를 너무 많이 줄 필요가 없다.예를 들어 이 ListView에는 500개의 item이 포함되어 있지만, 화면에는 최대 10조의 item이 표시되고, 나머지 데이터는 디스플레이를 준비하는 상태이다.
(3) 안드로이드 다중 VM Davlik에 대한 제한 사항이 필요합니다.안드로이드 장치의 앱이 실행되고, 앱을 열 때마다 최소한 하나의 독립된 가상 머신을 열 수 있습니다.이렇게 하면 시스템의 붕괴를 피할 수 있지만, 대가는 더 많은 메모리를 낭비하는 것이다.
4. GC가 자원을 자동으로 회수하는데 왜 OOM이 있습니까?
안드로이드의 GC는 특정한 알고리즘에 따라 사용하지 않는 자원을 회수하지만 gc는 일반적으로 주인이 없는 대상 메모리나 소프트 인용 자원을 회수한다.
소프트 참조된 이미지 리소스를 사용하면 OOM을 어느 정도 방지할 수 있습니다.
ps: 사용하지 않는 대상을null로 설정하는 것은 좋은 습관입니다.그러나 더 좋은 방법은 사용하지 않는 그림이 바로recycle이다.때로는null을 설정해서 gc를 회수해도 늦을 때가 있기 때문입니다.
5、어떻게 하면 OOM이 생기는 것을 피할 수 있습니까?
SoftReference 참조를 통해 이미지 리소스 관리
SoftReference의hashmap을 만듭니다. 그림을 사용할 때 이hashmap에softreference가 있는지, softreference의 그림이 비어 있는지 확인하십시오. 만약 비어 있으면softreference에 그림을 불러오고haspmap을 추가합니다.
코드는 다음과 같습니다.
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.widget.ImageView;
/**
* :
*
*/
public class AsyncImageLoaderCore {
public Context context; //
public HashMap> imageCache;//
public AsyncImageLoaderCore(Context context) {
this.context = context;
this.imageCache = new HashMap>();
}
public Bitmap loadBitmap(final String imageUrl, final ImageView imageView, final ImageCallback imageCallback) {
if (imageCache.containsKey(imageUrl)) {
SoftReference softReference = imageCache.get(imageUrl);
if (softReference.get() != null)
return softReference.get();
}
final Handler handler = new Handler(new Callback() {
@Override
public boolean handleMessage(Message msg) {
imageCallback.imageLoaded((Bitmap) msg.obj, imageView, imageUrl);
return false;
}
});
new Thread() {
@Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = getHttpBitmap(imageUrl);
} catch (Exception e) {
e.printStackTrace();
return;
}
if (null != bitmap) {
imageCache.put(imageUrl, new SoftReference(bitmap));
handler.sendMessage(handler.obtainMessage(0, bitmap));
}
}
}.start();
return null;
}
private final int MAX_PIC_LENGTH = 200000;// [ , 200000]
private final int SAMPLE_SIZE = 14;// (1/14)[ ]
/**
*
*/
private Bitmap getHttpBitmap(String imgUrl) throws Exception {
URL htmlUrl = new URL(imgUrl);
URLConnection connection = htmlUrl.openConnection();
HttpURLConnection conn = (HttpURLConnection) connection;
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = conn.getInputStream();
byte[] bytes = changeToBytes(inputStream);
if (bytes.length < MAX_PIC_LENGTH) {
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
} else if (bytes.length < MAX_PIC_LENGTH * SAMPLE_SIZE) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = SAMPLE_SIZE;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
}
return null;
}
/**
*
*/
public byte[] changeToBytes(InputStream inputStream) throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];//
int len = 0;
while ((len = inputStream.read(buffer)) != -1)
{
outputStream.write(buffer, 0, len);
}
inputStream.close();
return outputStream.toByteArray();
}
/**
*
*/
public interface ImageCallback {
public void imageLoaded(Bitmap bitmap, ImageView imageView, String imageUrl);
}
}