12
votes

Les fuites de mémoire sont-elles totalement absentes dans les applications Java?

Duplicaté possible:

Créer une fuite de mémoire avec Java

Il y a un "collecteur à ordures" en Java, mais cela signifie-t-il que les fuites de mémoire sont totalement absentes dans une application Java? Sinon, comment et pourquoi se produisent-ils?

Je suis plus intéressé par les scénarios dans les applications utilisant Javase.


1 commentaires

Il y a un thread ici discuter de la création d'une fuite de mémoire en Java.


5 Réponses :


17
votes

Non - Les fuites de mémoire peuvent toujours exister en Java. Ils sont juste d'un "type différent".

wiki: fuite de mémoire

Une fuite de mémoire, en informatique (ou une fuite, dans ce contexte), se produit lorsqu'un programme informatique consomme de la mémoire mais est impossible de le libérer [la mémoire] Retour au système d'exploitation . < / p>

Dans le cas de Java IT (normalement), c'est quand un objet inutilisé / inutilisé n'est jamais éligible pour la récupération. Par exemple, un objet peut être caché dans une liste globale et jamais supprimé même si l'objet n'est jamais accédé ultérieurement. Dans ce cas, le JVM ne libère pas l'objet / la mémoire - il ne peut pas - parce que l'objet pourrait être nécessaire plus tard, même s'il jamais est < / em>.

(comme à l'écart, certains objets, tels que directement alloués par des bytebuffers consommer également de la mémoire "hors de la JVM" qui pourrait ne pas être récupéré de manière rapide en raison de la nature des finaliseurs et de la pression de mémoire .)

dans le cas de Java, une "fuite de mémoire" est une question sémantique et pas tant de problème de "ne pas pouvoir publier en aucune circonstance". Bien sûr, avec un code Buggy Jni / JNA, tous les paris sont éteints; -)

codage heureux.


5 commentaires

En suivant, aucun collecteur d'ordures ne peut toujours récupérer toute la mémoire inutilisée. Il est prudemment impossible de construire un GC capable de détecter si un certain morceau de mémoire ne sera plus jamais utilisé, la plupart des GC utilisent si la mémoire est accessible en tant que substitution.


Merci pour une réponse rapide PST. La question que vous avez mentionnée a raison, mais c'est plus à cause de pratiques de programmation (mauvaises), n'est-ce pas? Supposons qu'il y ait des objets dans la mémoire qui sont "vraiment" éligibles pour la récupération, seront-ils certainement récupérés par JVM? avec certitude?


@ 10101010 Objets recouvris, ceux qui ne sont pas fortement accessibles à partir d'une racine, seront récupérés "à un moment donné" , oui. Cependant, dans le cas d'objets qui libèrent une mémoire "natif" dans le finaliseur, il peut être possible que la mémoire ("natif") ne soit pas suffisamment libérée - même si elle pourrait être - et donc pourrait entraîner un [prématuré] OOM.


Quickble mineur: Dans une JVM parfaite, le GC récupérera toujours tous les objets qui ne sont plus accessibles. Mais en raison de bugs JVM et de limitations de la capacité de la GC à calculer la portée de la portée, il existe des moyens de conserver de grandes quantités de données (classes chargeuses par exemple) enracinées à des fins de GC, tout en étant "accessible" dans le sens du code Java normal pouvant être capable à la déréférence et lire les valeurs d'objet correspondantes.


J'ai déjà exposé cela avec un motif d'observateur mal mis en œuvre. Des fuites de mémoire, existent définitivement.



1
votes

Les fuites de mémoire en Java sont très possibles. Voici un bon article qui a un exemple en utilisant Core Java . Fondamentalement, une fuite de mémoire se produit en Java lorsque le collecteur des ordures ne peut pas récupérer un objet car l'application détient une référence à celle qu'elle ne se libère pas, même si l'objet lui-même pourrait ne plus être utilisé. Le moyen le plus simple de créer une fuite de mémoire dans Java est d'avoir votre application détenir une référence à quelque chose, mais pas l'utiliser.

Dans l'exemple, l'objet inutilisé est une liste statique et l'ajout de choses à cette liste fera à terme que le JVM soit à court de mémoire. Les collections statiques sont une source assez courante de "fuites", car elles sont généralement vécues et mutables.


0 commentaires

2
votes

dépend de la manière dont vous définissez une fuite de mémoire.

Si vous signifiez spécifiquement avoir une mémoire allouée qui n'est plus référencée par une racine de mémoire, non, le collecteur des ordures finira éventuellement à nettoyer tous ceux-ci.

Si vous voulez dire que votre empreinte de mémoire augmente sans être liée, c'est facilement possible. Vous avez simplement une certaine collection référencée par un champ statique et est constamment ajouté à.


0 commentaires

1
votes

Il y a quelques bonnes réponses jusqu'à présent. Je ne veux pas recréer ces messages, alors je vais simplement ajouter qu'une chose que la plupart des gens ne pensent pas à ce sujet dans le cadre de ce sujet sont des fuites de code natif fonctionnant via JNI. Le code natif en cours d'exécution via JNI utilise l'espace de démarrage de JVM pour allouer la mémoire. Donc, si votre application utilise un code natif en cours d'exécution via JNI qui a une fuite, votre application a une fuite.


0 commentaires

1
votes

Tout objet comportant un ou plusieurs les références les ne sera pas collecté à la poubelle. Ainsi, tant que certaines variables (statiques, dans le tas, ou dans la pile) font référence à un objet, cet objet continuera d'occuper un espace mémoire non récupéré.

Les ressources non claires (comme des sockets comme des connexions JDBC, etc.) et des collections statiques en croissance constante sont quelques-unes des producteurs de fuites mieux connus.


0 commentaires