web-dev-qa-db-fra.com

Ramasse-miettes dans Android

J'ai vu beaucoup de réponses Android qui suggèrent d'appeler le ramasse-miettes dans certaines situations.

Est-ce une bonne pratique de demander le ramasse-miettes dans Android avant de faire une opération gourmande en mémoire? Si non, devrais-je l'appeler uniquement si je reçois une erreur OutOfMemory?

Y a-t-il autre chose que je devrais utiliser avant de faire appel au ramasse-miettes?

102
hpique

Pour les versions antérieures à .0 nid d'abeille: Oui, appelerSystem.gc().

J'ai essayé de créer des bitmaps, mais je obtenais toujours "erreur de mémoire insuffisante de la machine virtuelle". Mais, quand j'ai appelé System.gc() d'abord, tout était ok.

Lors de la création de bitmaps, Android échoue souvent avec des erreurs de mémoire insuffisante, et n'essaie pas de commencer par ramasser les ordures). Par conséquent, appelez System.gc(), et vous avez assez de mémoire pour créer des bitmaps.

Si je crée des objets, je pense que System.gc Sera appelé automatiquement si nécessaire, mais pas pour créer des bitmaps. Ça échoue.

Je recommande donc d'appeler manuellement System.gc() avant de créer des bitmaps.

139
steve

De manière générale, en présence d’un ramasse-miettes, il est jamais de bonne pratique d'appeler manuellement le CPG. Un GC est organisé autour d'algorithmes heuristiques qui fonctionnent mieux lorsqu'ils sont laissés à eux-mêmes. L'appel manuel du CPG réduit souvent les performances.

Occasionnellement, dans certaines situations relativement rares, on peut constater qu'un CPG particulier se trompe, et un appel manuel au GC peut améliorer les choses, en termes de performances. En effet, il n'est pas vraiment possible d'implémenter un GC "parfait" qui gérera la mémoire de manière optimale dans tous les cas. De telles situations sont difficiles à prévoir et dépendent de nombreux détails de mise en œuvre subtils. La "bonne pratique" consiste à laisser le GC fonctionner seul; un appel manuel au GC est l'exception, qui ne devrait être envisagée qu'après qu'un problème de performance ait été dûment constaté.

115
Thomas Pornin

Manque de mémoire dans Android est très courante si nous ne gérons pas correctement le bitmap. La solution au problème serait:

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);

Dans le code ci-dessus, je viens d'essayer de recycler le bitmap, ce qui vous permettra de libérer de la mémoire, de sorte qu'il ne risque pas y avoir trop de mémoire. J'ai essayé, cela a fonctionné pour moi.

Si le problème persiste, vous pouvez également ajouter ces lignes.

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

pour plus d'informations, consultez ce lien

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


NOTE: En raison de la "pause" momentanée causée par l'exécution de gc, il est non recommandé de le faire avant chaque allocation de bitmap.

La conception optimale est:

  1. Libérez tous les bitmaps dont vous n'avez plus besoin , à l'aide du code if / recycle / null Affiché. (Faites une méthode pour aider avec ça.)

  2. System.gc();

  3. Attribuez les nouvelles bitmaps.

26
yogesh

Si vous obtenez une erreur OutOfMemoryError, il est généralement trop tard pour appeler le ramasse-miettes ...

Voici la citation de Android Développeur:

La plupart du temps, la récupération de place s'effectue à cause de tonnes de petits objets éphémères et certains éboueurs, tels que les éboueurs de génération, peuvent optimiser la collecte de ces objets afin que l'application ne soit pas interrompue trop souvent. Le ramasse-miettes Android n'est malheureusement pas en mesure d'effectuer de telles optimisations et la création d'objets de courte durée dans des chemins de code critiques pour les performances est donc très coûteuse pour votre application.

Donc, à ma connaissance, il n’est pas urgent d’appeler le gc. Il est préférable de consacrer plus d'efforts à éviter la création inutile d'objets (comme la création d'objets dans des boucles).

19
Andreas_D

Mon application gère beaucoup d'images et elle est morte avec une erreur OutOfMemoryError. Cela m'a aidé. Dans le fichier manifeste.xml Ajouter

<application
....
   Android:largeHeap="true"> 
7
Klykoo

Il semble que System.gc() ne fonctionne pas sur Art Android 6.0.1 Nexus 5x, j'utilise donc Runtime.getRuntime().gc(); à la place.

7
cmicat

En règle générale, vous ne devez pas appeler explicitement GC avec System.gc (). Il y a même le IO lecture ( http://www.youtube.com/watch?v=_CruQY55HOk )) où ils expliquent ce que le journal des pauses du GC signifie et dans qu'ils déclarent également ne jamais appeler System.gc (), car Dalvik sait mieux que vous le faire.

D'un autre côté, comme mentionné ci-dessus, les réponses du processus GC dans Android (comme tout le reste) sont parfois boguées. Cela signifie que les algorithmes GC de Dalvik ne sont pas au même niveau que les machines virtuelles Hockpot ou JRockit et risquent d'obtenir des résultats Il est parfois difficile d’allouer des objets bitmap, car il utilise la mémoire Heap et Non Heap et parce qu’une seule instance lâche d’un objet bitmap sur un périphérique contraint en mémoire est suffisante pour vous donner une exception OutOfMemory. l'appeler après que vous n'ayez plus besoin de cette bitmap est généralement suggéré par de nombreux développeurs et même considéré comme une bonne pratique par certaines personnes.

La meilleure pratique consiste à utiliser .recycle () sur un bitmap, car c'est la raison pour laquelle cette méthode est conçue, car elle marque la mémoire native du bitmap comme pouvant être supprimée en toute sécurité. Gardez à l'esprit que cela dépend beaucoup de la version, ce qui signifie qu'il sera généralement requis sur les anciennes Android (Pre 3.0 je pense)), mais ne sera pas requis sur les versions ultérieures. beaucoup d'utilisation sur les nouvelles versions ether (ne faites pas ceci dans une boucle ou quelque chose comme ça). Le nouveau runtime d'ART a beaucoup changé ici car ils ont introduit une "partition" spéciale pour les gros objets mais je pense que ça ne fera pas beaucoup de mal à faites-le avec ART Ether.

Également une note très importante sur System.gc (). Cette méthode n'est pas une commande à laquelle Dalvik (ou les machines virtuelles) est obligé de répondre. Considérez cela plus comme dire à la machine virtuelle "Pourriez-vous s'il vous plaît faire la collecte des ordures si ce n'est pas un problème".

6
PSIXO

Meilleur moyen d'éviter le MOO lors de la création d'un bitmap,

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

3
prabhu

Il n'est pas nécessaire d'appeler le ramasse-miettes après un OutOfMemoryError.

C'est Javadoc déclare clairement:

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.

Ainsi, le ramasse-miettes a déjà essayé de libérer de la mémoire avant de générer l'erreur, mais il a échoué.

2
perdian

Je dirais non, car le documentation du développeur sur RAM utilisation indique:

...
GC_EXPLICIT

Un GC explicite, comme lorsque vous appelez gc () (lequel vous devriez éviter appeler et fait plutôt confiance au GC pour s’exécuter en cas de besoin).

...

J'ai souligné la partie pertinente en gras.

Jetez un coup d’œil à la série YouTube, Android Performance Patterns - Elle vous montrera des astuces pour gérer l’utilisation de la mémoire de votre application (par exemple, utilisez ArrayMaps et SparseArrays d’Android à la place de HashMaps).

2

Note rapide pour développeurs Xamarin.

Si vous souhaitez appeler System.gc() dans les applications Xamarin.Android, vous devez appeler Java.Lang.JavaSystem.Gc()

2
Denis Gordin