Que fait le flag JCl CMSClassUnloadingEnabled?

Je ne peux pas pour la vie trouver une définition de ce que fait réellement l’ CMSClassUnloadingEnabled Java VM de CMSClassUnloadingEnabled , à part quelques définitions de haut niveau très floues telles que “se débarrasse de vos problèmes de PermGen” ( ce qui n’est pas le cas ).

J’ai regardé sur le site de Sun / Oracle, et même la liste d’options ne dit pas réellement ce qu’elle fait.

Sur la base du nom de l’indicateur, je suppose que le ramasse-miettes CMS ne décharge pas par défaut les classes et que cet indicateur l’active, mais je ne peux pas en être sûr.

Mise à jour Cette réponse est pertinente pour Java 5-7, Java 8 a résolu ce problème: https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Les félicitations vont à mt. uulu

Pour Java 5-7:

Le standard Oracle / Sun VM sur le monde est le suivant: les classes sont éternelles. Donc, une fois chargées, elles restnt en mémoire même si personne ne s’en soucie plus. Ce n’est généralement pas un problème puisque vous n’avez pas beaucoup de classes purement “setup” (= utilisé une fois pour la configuration et plus jamais une fois). Donc, même s’ils prennent 1 Mo, on s’en fout.

Mais récemment, nous avons des langages comme Groovy, qui définissent les classes à l’exécution. Chaque fois que vous exécutez un script, une ou plusieurs nouvelles classes sont créées et restnt dans PermGen pour toujours. Si vous utilisez un serveur, cela signifie que vous avez une fuite de mémoire.

Si vous activez CMSClassUnloadingEnabled le GC balaye également PermGen et supprime les classes qui ne sont plus utilisées.

[EDIT] Vous devrez également activer UseConcMarkSweepGC (merci à Sam Hasler ). Voir cette réponse: https://stackoverflow.com/a/3720052/2541

Selon l’article du blog La liste la plus complète d’options -XX pour Java JVM , il détermine si le déchargement de classe est activé sous le garbage collector du CMS. La valeur par défaut est false . Il existe une autre option appelée ClassUnloading qui est true par défaut et qui (probablement) affecte les autres ramasse-miettes.

L’idée est que si le CPG détecte qu’une classe précédemment chargée n’est plus utilisée nulle part dans la JVM, elle peut récupérer la mémoire utilisée pour contenir le bytecode des classes et / ou le code natif.

La définition de CMSClassUnloadingEnabled peut aider à résoudre votre problème de permgen si vous utilisez actuellement le collecteur du CMS . Mais les chances sont que vous n’utilisez pas le CMS, ou que vous ayez une véritable fuite de mémoire liée à classloader. Dans ce dernier cas, votre classe n’apparaîtra jamais au GC comme inutilisée … et ne sera donc jamais déchargée.


Aaron Digulla dit que “les cours sont pour toujours”. Ce n’est pas ssortingctement vrai, même dans le monde purement Java. En fait, la durée de vie d’une classe est liée à son chargeur de classes. Donc, si vous pouvez faire en sorte qu’un classloader soit récupéré (et ce n’est pas toujours chose facile), les classes qu’il a chargées seront également récupérées.

En fait, c’est ce qui se passe lorsque vous effectuez un redéploiement à chaud d’une application Web. (Ou du moins, c’est ce qui devrait arriver si vous pouvez éviter les problèmes qui conduisent à une fuite de stockage de permgen.)

Un exemple où cela est utile:

Paramètre -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled sur notre JVM Weblogic 10.3 a permis de résoudre un problème où l’implémentation JAX-WS créait une nouvelle classe proxy pour chaque appel de service Web, entraînant éventuellement des erreurs de mémoire.

Ce n’était pas sortingvial de tracer. Le code suivant renvoie toujours la même classe proxy pour le port

 final MyPortType port = Service.create( getClass().getResource("/path/to.wsdl"), new QName("http://www.example.com", "MyService")) .getPort( new QName("http://www.example.com", "MyPortType"), MyPortType.class); 

En interne, ce proxy a délégué à une instance de weblogic.wsee.jaxws.spi.ClientInstance , qui a de nouveau délégué à une nouvelle classe $Proxy[nnnn]n été incrémenté à chaque appel. Lors de l’ajout des indicateurs, n était toujours incrémenté, mais au moins ces classes temporaires étaient supprimées de la mémoire.

D’une manière plus générale, cela peut être très utile lors de l’utilisation intensive de la reflection Java et des proxies via java.lang.reflect.Proxy