Ich bekomme sporadisch eine OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB) in einer meiner Apps. Was kann ich tun, um dies zu diagnostizieren?
01-09 10:32:02.079: E/dalvikvm(8077): Out of memory: Heap Size=49187KB, Allocated=41957KB, Limit=49152KB
01-09 10:32:02.079: E/dalvikvm(8077): Extra info: Footprint=48611KB, Allowed Footprint=49187KB, Trimmed=7852KB
01-09 10:32:02.079: D/skia(8077): --- decoder->decode returned false
01-09 10:32:02.079: D/AndroidRuntime(8077): Shutting down VM
01-09 10:32:02.079: W/dalvikvm(8077): threadid=1: thread exiting with uncaught exception (group=0x40a97228)
01-09 10:32:02.079: E/AndroidRuntime(8077): FATAL EXCEPTION: main
01-09 10:32:02.079: E/AndroidRuntime(8077): java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:486)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.loadDrawable(Resources.java:2044)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.getDrawable(Resources.java:675)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.view.View.setBackgroundResource(View.java:11776)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.ImageLoader.DisplayImage(ImageLoader.java:81)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.MatchActivity$MatchAsyncTask.onPostExecute(MatchActivity.java:1768)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.finish(AsyncTask.java:602)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.access$600(AsyncTask.java:156)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Handler.dispatchMessage(Handler.java:99)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Looper.loop(Looper.java:156)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.app.ActivityThread.main(ActivityThread.java:4987)
01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invoke(Method.java:511)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-09 10:32:02.079: E/AndroidRuntime(8077): at dalvik.system.NativeStart.main(Native Method)
01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Process: com.blsk.bigtoss
01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Package: com.blsk.bigtoss v6 (1.2)
01-09 10:32:02.129: E/EmbeddedLogger(1612): Application Label: Cricket
Sie versuchen, eine Bitmap in eine ImageView zu laden. Offensichtlich ist die Bitmap, die Sie manchmal laden, zu groß, um in den Speicher zu passen. Sie müssen das Bild beim Lesen verkleinern. Sehen Sie sich inSampleSize an
– Greg Ennis
9. Januar 14 um 5:12 Uhr
@NagarjunaReddy hast du dein Problem gelöst oder nicht?
– dipali
9. Januar 14 um 5:28 Uhr
Nein, noch nicht versucht … @dipali
– NagarjunaReddy
9. Januar 14 um 5:30 Uhr
was? hast du dein prblm nicht gelöst?
– dipali
9. Januar 14 um 5:34 Uhr
Dieser Fehler tritt nur manchmal auf, nicht immer @dipali
– NagarjunaReddy
9. Januar 14 um 5:43 Uhr
vielleicht hilft dir das weiter?
Manifest hinzufügen
Android > v3
<application
....
android:largeHeap="true">
Die Verwendung von largeHeap wird nicht in allen Fällen empfohlen, verwenden Sie es bitte sehr vorsichtig, da es andere laufende Anwendungen verlangsamen und auch die Reaktionsfähigkeit Ihrer App beeinträchtigen kann, da der Garbage Collector häufiger angefordert wird. Weitere Informationen finden Sie in dieser Rede von Google i/o youtube.com/watch?v=_CruQY55HOk
– Laune
17. Juli 15 um 12:49 Uhr
Fordern Sie niemals einen großen Heap an, nur weil Ihnen der Arbeitsspeicher ausgeht und Sie eine schnelle Lösung benötigen – Sie sollten ihn nur verwenden, wenn Sie genau wissen, wo Ihr gesamter Arbeitsspeicher zugewiesen wird und warum er beibehalten werden muss. Doch selbst wenn Sie sicher sind, dass Ihre App den großen Haufen rechtfertigen kann, sollten Sie es so weit wie möglich vermeiden, sie anzufordern. sehen developer.android.com/training/articles/memory.html
– Adnan Ali
5. September 16 um 10:41 Uhr
CommonSenseCode
Häufige Korrekturen:
1. Korrigieren Sie Ihre Kontexte:
Versuchen Sie es mit dem passenden Kontext: Zum Beispiel, da ein Toast in vielen Aktivitäten statt nur in einer zu sehen ist, verwenden Sie ihn getApplicationContext() für Toasts, und da Dienste weiterlaufen können, obwohl eine Aktivität beendet ist, starten Sie einen Dienst mit:
Intent myService = new Intent(getApplicationContext(), MyService.class)
Verwenden Sie diese Tabelle als Kurzanleitung für den geeigneten Kontext:
2. Überprüfen Sie, ob Sie Ihre Dienste tatsächlich beenden.
Zum Beispiel habe ich einen IntentService, der Google Location Service API verwendet. Und ich habe vergessen anzurufen googleApiClient.disconnect();:
//Disconnect from API onDestroy()
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, GoogleLocationService.this);
googleApiClient.disconnect();
}
3. Überprüfen Sie die Verwendung von Bildern und Bitmaps:
Wenn Sie Quadrate verwenden Bibliothek Picasso Ich habe festgestellt, dass ich Speicher verloren habe, indem ich die nicht verwendet habe .fit(), das meinen Speicherbedarf drastisch von durchschnittlich 50 MB auf weniger als 19 MB reduziert hat:
Picasso.with(ActivityExample.this) //Activity context
.load(object.getImageUrl())
.fit() //This avoided the OutOfMemoryError
.centerCrop() //makes image to not stretch
.into(imageView);
4. Wenn Sie Rundfunkempfänger verwenden, deregistrieren Sie diese.
5. Wenn Sie verwenden java.util.Observer (Beobachtermuster):
Das Laden von Bitmaps in der Bildansicht war schon immer eine Ursache für Speichermangel. Dies ist sehr häufig, daher müssen wir Bildansichten und Bitmaps sehr sorgfältig behandeln. Was Sie tun können, ist, während Sie eine beliebige Hintergrund-Bitmap für Ihre Bildansicht festlegen, zuerst das Drawable abrufen und es recyceln, damit es aus dem Speicher entfernt wird, und dann die neue Bitmap festlegen. Dies hilft, OOM-Probleme zu vermeiden. Weiter. Sie können BitmapFactoryOptions verwenden, um die Größe Ihrer Bitmap zu reduzieren. mögen:
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_WIDTH
|| height_tmp / 2 < REQUIRED_HIGHT)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Warum es abgelehnt wird, lassen Sie mich auch den Grund dafür wissen. Wer es abgelehnt hat, erwähnt bitte den Grund dafür.
– Avtar Guleria
9. Januar 14 um 5:18 Uhr
Obwohl dies in der Theorie eine nette Idee ist, funktioniert es in der Praxis nicht so gut. Der Aufruf von Recycle() ist lediglich ein Hinweis an den GC, Speicher zurückzufordern. Es kann sein, dass es nicht zurückgefordert wird, wenn Sie Ihr neues Image erstellen, und kann daher immer noch zum Absturz Ihrer Anwendung führen. Noch wichtiger ist jedoch, dass der GC den Speicher automatisch zurückfordert, wenn er über die nächsten paar CG-Zyklen läuft.
– Das es
9. Januar 14 um 5:37 Uhr
Wirklich, warum jemand runtergestimmt hat, er / sie ist ein echter Nerd.. Meistens funktioniert es.. Es hat für mich funktioniert.. in meinem Projekt..
– Shakeeb Ayaz
9. Januar 14 um 5:45 Uhr
Ich wollte das gleiche beantworten, also +1
– Shakeeb Ayaz
9. Januar 14 um 5:47 Uhr
Danke. Shakeeb Ayaz. @TheIT, meinst du, dass die Recycling-Methode auf Bitmap nicht nützlich ist oder was, wenn das dann in welcher Situation wir es verwenden sollten?
– Avtar Guleria
9. Januar 14 um 5:51 Uhr
Bevor Sie Bilder in den Speicher laden, komprimieren Sie Ihre Bilder mit
Bitmap original = BitmapFactory.decodeStream(getAssets().open("1024x768.jpg"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.PNG, 100, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
Log.e("Original dimensions", original.getWidth()+" "+original.getHeight());
Log.e("Compressed dimensions", decoded.getWidth()+" "+decoded.getHeight());
Wenn Sie Ihre Bitmap von einer Ressource beziehen, hängt die Bitmap-Dimension in diesem Fall von der Bildschirmdichte des Telefons ab
Dies kann mehrere Gründe haben, möglicherweise behalten Sie Verweise auf andere Teile Ihres Codes zu lange bei. Möglicherweise laden Sie zu große Bitmaps, die zusammen mit Festhalten an vielen Referenzen gibt dir OOM usw.
Normalerweise, wenn ein OOM auftritt a hprof (Schnappschuss des Heap) wird im Stammverzeichnis der SD-Karte (oder im internen Speicher, wenn keine SD-Karte vorhanden ist) erstellt, die von Tools wie gelesen werden kann Eklipse MAT (in den Android-Tools enthalten, wenn Sie Eclipse verwenden). Zuerst muss man evtl. die hprof mit umwandeln hprof-conv Werkzeug. Hier ist ein Tutorial zur Verwendung von Eclipse MAT: Untersuchung Ihrer RAM-Nutzung. Der Bericht über Leckverdächtige ist eine gute erste Lektüre, wenn hprof in Eclipse MAT geladen wird
Es gibt auch mehrere beliebte Bildladebibliotheken wie z universeller Bildlader und Picasso verfügbar, die mit Leichtigkeit das tun, was Sie brauchen.
@NagarjunaReddy hat diese Antwort mit weiteren Ideen aktualisiert, was Sie tun könnten. Ich würde mit der Analyse beginnen hprof Um zu sehen, ob Sie an zu vielen Refs festhalten, können Sie, wenn dies nicht der Fall ist, einige Bildbibliotheken verwenden, die Bilder zwischenspeichern und sie problemlos an Ihre erforderlichen Ansichtsgrößen anpassen.
public String BitMapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String temp = Base64.encodeToString(b, Base64.DEFAULT);
return temp;
}
public static void setImagesNew(LinearLayout linearLayout, String pathName,
Activity activity) {
Bitmap bmp = decodeSampledBitmapFromResource(pathName,
getDeviceWidth(activity), getDeviceHeight(activity));
linearLayout.setBackgroundDrawable(bmp);
bmp = null;
System.gc();
Runtime.getRuntime().gc();
}
public static Bitmap decodeSampledBitmapFromResource(String pathName,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(pathName, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
@SuppressLint("NewApi")
public static int getDeviceWidth(Activity activity) {
int deviceWidth = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceWidth = size.x;
} else {
Display display = windowManager.getDefaultDisplay();
deviceWidth = display.getWidth();
}
return deviceWidth;
}
@SuppressLint("NewApi")
public static int getDeviceHeight(Activity activity) {
int deviceHeight = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceHeight = size.y;
} else {
Display display = windowManager.getDefaultDisplay();
deviceHeight = display.getHeight();
}
return deviceHeight;
}
Bitte legen Sie alle Funktionen in Ihre Aktivität und rufen Sie nur an setImageNew() und Parameter in imageview, sdcardpathname und activity übergeben
Ich hoffe, es wird nicht abstürzen, nachdem Sie diesen Code implementiert haben. weil ich das gleiche problem habe wie du..
@NagarjunaReddy hat diese Antwort mit weiteren Ideen aktualisiert, was Sie tun könnten. Ich würde mit der Analyse beginnen hprof Um zu sehen, ob Sie an zu vielen Refs festhalten, können Sie, wenn dies nicht der Fall ist, einige Bildbibliotheken verwenden, die Bilder zwischenspeichern und sie problemlos an Ihre erforderlichen Ansichtsgrößen anpassen.
Sie versuchen, eine Bitmap in eine ImageView zu laden. Offensichtlich ist die Bitmap, die Sie manchmal laden, zu groß, um in den Speicher zu passen. Sie müssen das Bild beim Lesen verkleinern. Sehen Sie sich inSampleSize an
– Greg Ennis
9. Januar 14 um 5:12 Uhr
@NagarjunaReddy hast du dein Problem gelöst oder nicht?
– dipali
9. Januar 14 um 5:28 Uhr
Nein, noch nicht versucht … @dipali
– NagarjunaReddy
9. Januar 14 um 5:30 Uhr
was? hast du dein prblm nicht gelöst?
– dipali
9. Januar 14 um 5:34 Uhr
Dieser Fehler tritt nur manchmal auf, nicht immer @dipali
– NagarjunaReddy
9. Januar 14 um 5:43 Uhr