Comment traiter l'erreur "java.lang.OutOfMemoryError : Java heap space&quot ; erreur ?

J'écris une application Swing côté client (concepteur de polices graphiques) sur Java 5. Récemment, j'ai rencontré l'erreur java.lang.OutOfMemoryError : Java heap space parce que je ne suis pas prudent sur l'utilisation de la mémoire. L'utilisateur peut ouvrir un nombre illimité de fichiers, et le programme garde les objets ouverts en mémoire. Après une recherche rapide, j'ai trouvé [Ergonomics in the 5.0 Java Virtual Machine][1] et d'autres personnes disant que sur une machine Windows, la JVM fixe par défaut la taille maximale du tas à 64MB.

Dans cette situation, comment dois-je gérer cette contrainte ?

Je pourrais augmenter la taille maximale du tas en utilisant l'option ligne de commande de java, mais cela nécessiterait de déterminer la RAM disponible et d'écrire un programme ou un script de lancement. De plus, augmenter jusqu'à un maximum fini ne résout pas en fin de compte le problème.

Je pourrais réécrire une partie de mon code pour que les objets persistent fréquemment dans le système de fichiers (utiliser une base de données revient au même) afin de libérer de la mémoire. Cela pourrait fonctionner, mais c&#8217est probablement aussi beaucoup de travail.

Si vous pouvez m'indiquer les détails des idées ci-dessus ou des alternatives comme mémoire virtuelle automatique, extension dynamique de la taille du tas, ce serait formidable.

[1] : http://java.sun.com/docs/hotspot/gc5.0/ergo5.html

Solution

En fin de compte, vous avez toujours un maximum fini de tas à utiliser, quelle que soit la plate-forme sur laquelle vous travaillez. Sous Windows 32 bits, cette limite est d'environ 2GB (pas spécifiquement le tas mais la quantité totale de mémoire par processus). Il se trouve que Java a choisi de réduire la valeur par défaut (sans doute pour que le programmeur ne puisse pas créer des programmes ayant une allocation de mémoire incontrôlée sans se heurter à ce problème et devoir examiner exactement ce qu'il fait).

Il existe donc plusieurs approches possibles pour déterminer la quantité de mémoire dont vous avez besoin ou pour réduire la quantité de mémoire que vous utilisez. L'une des erreurs les plus courantes dans les langages à ramassage d'ordures tels que Java ou C# consiste à conserver des références à des objets que vous n'utilisez plus ou à allouer de nombreux objets alors que vous pourriez réutiliser ces derniers. Tant que les objets ont une référence, ils continueront à utiliser l'espace du tas car le ramasseur de déchets ne les supprimera pas.

Dans ce cas, vous pouvez utiliser un profileur de mémoire Java pour déterminer quelles méthodes de votre programme allouent un grand nombre d'objets et ensuite déterminer s'il existe un moyen de s'assurer qu'ils ne sont plus référencés, ou de ne pas les allouer en premier lieu. Une option que j'ai utilisée dans le passé est "JMP&quot ; .

Si vous déterminez que vous allouez ces objets pour une raison précise et que vous avez besoin de conserver des références (selon ce que vous faites, cela peut être le cas), il vous suffit d'augmenter la taille maximale du tas au démarrage du programme. Cependant, une fois que vous aurez établi le profil de la mémoire et compris comment vos objets sont alloués, vous devriez avoir une meilleure idée de la quantité de mémoire dont vous avez besoin.

En général, si vous ne pouvez pas garantir que votre programme s'exécutera dans une certaine quantité de mémoire (peut-être en fonction de la taille de l'entrée), vous rencontrerez toujours ce problème. Ce n'est qu'après avoir épuisé toutes ces possibilités que vous devrez envisager la mise en cache des objets sur le disque, etc. À ce stade, vous devriez avoir une très bonne raison de dire : " J'ai besoin de X Go de mémoire " pour quelque chose et vous ne pouvez pas contourner ce problème en améliorant vos algorithmes ou vos modèles d'allocation de mémoire. Généralement, ce ne sera le cas que pour les algorithmes opérant sur de grands ensembles de données (comme une base de données ou un programme d'analyse scientifique) et c'est alors que des techniques comme la mise en cache et les E/S mappées en mémoire deviennent utiles.

Commentaires (1)

Exécutez Java avec l'option de ligne de commande -Xmx, qui définit la taille maximale du tas.

Voir ici pour plus de détails.

Commentaires (3)

Oui, avec -Xmx vous pouvez configurer plus de mémoire pour votre JVM. Pour être sûr de ne pas perdre ou gaspiller de la mémoire. Faites un vidage du tas et utilisez [l'analyseur de mémoire d'Eclipse][1] pour analyser votre consommation de mémoire.

[1] : http://www.eclipse.org/mat/

Commentaires (1)