mai
2008
Java Quiz #13
Une classe Java peut-elle être déchargée de la mémoire ?
Réponse : La réponse est oui, dixit la spécification du langage Java (chapitre 12.7), mais ce n'est pas obligatoire.
Ainsi, le gestionnaire de mémoire de la machine virtuelle de Sun, HotSpot, gère les classes (les instances de la classe Class
, et toutes les autres données d'introspection) comme des objets. Son ramasse-miettes peut donc libérer la mémoire qu'une classe occupe lorsqu'elle n'est plus référencée, soit par une instance, soit par le code d'une autre classe. Au passage, cela permet de libérer aussi la mémoire occupée par tous les attributs statiques de la classe.
Les machines virtuelles BEA JRockit et IBM font de même. Les 3 JVM proposent d'ailleurs une option non standard -Xnoclassgc
, qui permet de bloquer ce mécanisme.
Question subsidiaire : Comment bloquer à coup sûr le déchargement d'une classe, et s'assurer qu'elle existera jusqu'à ce que la JVM s'arrête ?
La solution la plus classique et la plus simple est de s'assurer qu'un bout de code, qui ne cessera de s'exécuter qu'à la fin du programme, garde une référence sur l'instance de la classe Class
qui la désigne, ou sur un attribut statique de cette classe. On verra dans d'autres quizz qu'il existe aussi d'autres cas beaucoup plus tordus (et difficiles à détecter), qui s'apparentent plus à des fuites mémoire.
Commentaires
Si je comprends bien ce que je lis sur le sujet, le classloader par défaut est celui de System. Et on ne peut décharger une classe qu'en même temps que son classloader. Du coup si tu charges une classe en mémoire "de manière classique", tu ne peux pas la décharger (ça reviendrait à vouloir décharger System...). Il faut charger la classe via son propre classloader (je lis que le code de TomCat est un bon HowTo).
Lien : http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html
Je note "However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application." Est-ce que c'est de cette manière que Jython fonctionne ?
A priori, l'assertion «on ne peut décharger une classe qu'en même temps que son classloader» est fausse. Même s'il est probable que le classloader de bootstrap ait un fonctionnement particulier.
Je précise que le «classloader de bootstrap» (ou «classsloader primordial») n'est pas ce qu'on appelle le «classloader système» :
java.lang.System
,java.lang.Runtime
,java.lang.Thread
,java.lang.Exception
(et aussi, évidemment)java.lang.Object
. Ce classloader est d'ailleurs très particulier : il est natif (donc pas écrit en Java), et on ne peut le référencer que par "(ClassLoader) null
"...Ceci étant dit, la question pose le problème du déchargement des classes, pas celui de leur chargement. Si je fais le parallèle avec les objets, auriez-vous trouvé logique la réponse «les objets ne sont jamais déchargés de la mémoire parce que le langage Java prévoit une instruction new et aucune instruction delete» ? Si le classloader est responsable du chargement des classes en mémoire, est-ce forcément lui qui doit être responsable de leur déchargement ?
En relisant la question j'ai trouvé une réponse : "Quelle classe ?"