OVH Cloud OVH Cloud

Gestion de la mémoire

7 réponses
Avatar
Bruno Richard
Bonjour,

je ne comprends pas comment la JVM gère les ressources mémoire :

j'ai un vecteur d'objets.
je fais une simple boucle :

MonObject n;
Iterator ite = v.iterator();
while (ite.hasNext())
{
n = (MonObject) ite.next();

System.out.println("état mémoire : "
+Runtime.getRuntime().freeMemory()+ " de "
+Runtime.getRuntime().totalMemory());
}

Ce faisant, j'observe que la mémoire dispo
diminue régulièrement puis retrouve son
niveau initial, rediminue etc...

A mon avis, il ne devrait pas y avoir de variation
puisse aucun objet nouveau n'est créé.
Quelqu'un peut il m'expliquer ?

Merci
Bruno

7 réponses

Avatar
Pif
en fait il ne libère la mémoire que si c'est nécessaire ou
périodiquement .. du coup ca a un effet de dent de scie qui grimpes
jusqu'aux niveau spécifié dans le paramètre de la machine virtuelle...
avec n'importe quel code qui manipule des instances ou autre (donc
allocation / libération ) de mémoire on retrouve ce phénomène, c'est pas
franchement génant...

en pratique, tu fais des System.out.println avec des concaténation de
chaines de caractères, ... c'est de l'allocation de mémoire puisque t'as
déjà plusieur objets...
Avatar
Thibaut COFFINET
Bonjour,

en fait il ne libère la mémoire que si c'est nécessaire ou
périodiquement .. du coup ca a un effet de dent de scie qui grimpes
jusqu'aux niveau spécifié dans le paramètre de la machine virtuelle...
avec n'importe quel code qui manipule des instances ou autre (donc
allocation / libération ) de mémoire on retrouve ce phénomène, c'est pas
franchement génant...

en pratique, tu fais des System.out.println avec des concaténation de
chaines de caractères, ... c'est de l'allocation de mémoire puisque t'as
déjà plusieur objets...



OK mais je crois avoir compris (en discutant, de vive voix, avec lui par
ailleurs !) que les variations étaient TRES IMPORTANTES (jusqu'à
saturation de la mémoire)... donc les allocations de chaînes
n'expliquent pas ce phénomène.

Ses 400Mo de mémoire alloués (en paramètre de la JVM) sont RAPIDEMENT
utilisés, jusqu'à rendre son PC (Linux) inutilisable... jusqu'au kill du
process java.

D'autres idées pour lui ? merci d'avance.

Thibaut.

Avatar
Pif
je veus pas paraitre casse pied.. mais sur les trois lignes de codes
données auparavant... y'a pas de quoi remplir la mémoire !


aussi j'ai plusieurs propositions :
1 - envoie la classe avec le code... pasque c'est pas normal et les 5
lignes que tu nous as données n'expliquent pas tout... donc faut en
savoir plus...

2 - possibilité : si tu as beaucoup d'objets, ton system.out.println()
se fait ptet dans la console d'un environnement, du coup c'est pas ton
process en soit qui consomme des ressource, mais l'espece de console de
l'environnement intégré (eclipse ? jbuilder ? qui veut conserver en
mémoire toutes les sorties ... ca m'arrivait pas mal sous linux avec
jbuilder y'a quelques temps .... mais faut quand meme commencer à
vouloir afficher plusieurs dizaines de milliers de lignes pour saturer
la mémoire... combien d'object comporte ton itérateur ?
Avatar
Kupee
Bruno Richard wrote:
Bonjour,

je ne comprends pas comment la JVM gère les ressources mémoire :

j'ai un vecteur d'objets.
je fais une simple boucle :

MonObject n;
Iterator ite = v.iterator();
while (ite.hasNext())
{
n = (MonObject) ite.next();

System.out.println("état mémoire : "
+Runtime.getRuntime().freeMemory()+ " de "
+Runtime.getRuntime().totalMemory());
}

Ce faisant, j'observe que la mémoire dispo
diminue régulièrement puis retrouve son
niveau initial, rediminue etc...

A mon avis, il ne devrait pas y avoir de variation
puisse aucun objet nouveau n'est créé.
Quelqu'un peut il m'expliquer ?


Les concaténations de String avec + alouent un objet a chaque + en gros
donc chaque itération va alouer plusieurs Strings, après il faut voir la
taille de ton Vector ...

Avatar
Laurent Bossavit
Thibaut, Bruno,

D'autres idées pour lui ? merci d'avance.


Utiliser un "profiler" d'usage mémoire, comme hprof (livré avec Java),
OptimizeIt (Borland), JProbe, etc.

Autres outils:
http://enduouki.notlong.com (open source)
http://previtly.notlong.com (commerciaux)

A+

Avatar
Bruno Richard
Pif wrote:
je veus pas paraitre casse pied.. mais sur les trois lignes de codes
données auparavant... y'a pas de quoi remplir la mémoire !


aussi j'ai plusieurs propositions :
1 - envoie la classe avec le code... pasque c'est pas normal et les 5
lignes que tu nous as données n'expliquent pas tout... donc faut en
savoir plus...



un peu plus d'explications ce que je voulais faire:
je travaille en fait avec un client et un serveur.
je veux transférer des BufferedImage du client au serveur.

le client :

ImageObjet iobj;
MonObjet n;

ite = v.iterator();
n = null;
while (ite.hasNext())
{
n = (MonObjet) ite.next();
image = n.graphToJPEG(5);

iobj = new ImageObjet(nom,new ImageIcon(image));
// ImageObjet est un objet serializable qui contient
// simplement le nom de l'objet et l'ImageIcon

envoie_vers_serveur.sendObject(iobj);
}



le serveur :


while (clientadmin_webconseil_socket.isConnected())
{
o = clientadmin_to_webconseil.readObject();
if (o instanceof ImageObjet
{
//traitements
}
}


Qd j'essaye de transférer une centaine d'objets "ImageObjet",
la mémoire semble mal désallouée et tout plante.

j'ai remplacé l'ImageIcon transféré avec l'objet "ImageObjet"
par un tableau de byte et tout fonctionne :
la mémoire est désallouée régulièrement...

Etrange non ?

Avatar
Bruno Jouhier
Il y a de bonne chances que ton objet "icon" référence un objet "natif" du
système graphique (une ressource GDI sous windows) qui n'est pas gérée par
le garbage collector. Dans ce cas, il y a sans doute une méthode "dispose"
sur ton objet "icon" et il faut que tu l'appelles pour libérer correctement
la mémoire qui n'est pas sous le contrôle direct du GC.

Normalement, il devrait y avoir une méthode finalize() dans l'objet icon qui
libère la resource native, mais il se peut que ça ne soit pas le cas, ou
bien que les resources natives ne soient pas libérées rapidement (par
exemple à cause des modèles de threading COM si tu es sous windows).

Un conseil donc, appelle dispose() explicitement pour libérer les resources
"natives" dès que tu n'en as plus besoin.

Bruno;

"Bruno Richard" a écrit dans le message
de news: 43204611$0$27721$
Pif wrote:
je veus pas paraitre casse pied.. mais sur les trois lignes de codes
données auparavant... y'a pas de quoi remplir la mémoire !


aussi j'ai plusieurs propositions :
1 - envoie la classe avec le code... pasque c'est pas normal et les 5
lignes que tu nous as données n'expliquent pas tout... donc faut en
savoir plus...



un peu plus d'explications ce que je voulais faire:
je travaille en fait avec un client et un serveur.
je veux transférer des BufferedImage du client au serveur.

le client :

ImageObjet iobj;
MonObjet n;

ite = v.iterator();
n = null;
while (ite.hasNext())
{
n = (MonObjet) ite.next();
image = n.graphToJPEG(5);

iobj = new ImageObjet(nom,new ImageIcon(image));
// ImageObjet est un objet serializable qui contient
// simplement le nom de l'objet et l'ImageIcon

envoie_vers_serveur.sendObject(iobj);
}



le serveur :


while (clientadmin_webconseil_socket.isConnected())
{
o = clientadmin_to_webconseil.readObject();
if (o instanceof ImageObjet
{
//traitements
}
}


Qd j'essaye de transférer une centaine d'objets "ImageObjet",
la mémoire semble mal désallouée et tout plante.

j'ai remplacé l'ImageIcon transféré avec l'objet "ImageObjet"
par un tableau de byte et tout fonctionne :
la mémoire est désallouée régulièrement...

Etrange non ?