Que fait réellement JVM flag CMSClassUnloadingEnabled?

Je ne peux pas trouver de définition de ce que fait réellement le drapeau Java VM CMSClassUnloadingEnabled , à part quelques définitions très floues de haut niveau telles que" gets rid of your PermGen problems "( qu'il ne fait pas , btw).

j'ai regardé sur le site de Sun/Oracle, et même la liste des options ne dit pas réellement ce qu'il fait.

basé sur le nom du drapeau, je devine que le CMS Le collecteur d'ordures ne décharge pas par défaut les classes de déchargement, et ce drapeau l'allume - mais je ne peux pas en être sûr.

174
demandé sur Community 2010-07-26 16:51:20

3 réponses

mise à Jour Cette réponse est pertinente pour Java 5 À 7, Java 8 a ce fixe: https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanente-génération-et-metaspace Bravo, allez à mt.uulu

Pour Java 5-7:

la norme Oracle/Sun VM look sur le monde est: les Classes sont pour toujours. Donc une fois chargés, ils restent dans la mémoire même si plus personne ne s'en soucie. C'est généralement pas problème puisque vous n'avez pas beaucoup de classes purement "setup" (=utilisé une fois pour setup et puis jamais plus). Donc même s'ils prennent 1MB, qui s'en soucie.

mais dernièrement, nous avons des langues comme Groovy, qui définissent les classes à l'exécution. Chaque fois que vous exécutez un script, une (ou plusieurs) Nouvelle (S) Classe (S) sont créées et elles restent 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 balaiera PermGen, trop, et supprimer les classes qui ne sont plus utilisés.

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

209
répondu Aaron Digulla 2017-09-04 09:41:49

selon le billet de blog la liste la plus complète des options-XX pour Java JVM , il détermine si le déchargement de classe est activé sous le collecteur d'ordures CMS. La valeur par défaut est false . Il y a une autre option appelée ClassUnloading qui est true par défaut qui (présumément) affecte les autres collecteurs de déchets.

l'idée est que si le GC détecte qu'une classe précédemment chargée n'est plus utilisée dans la peut récupérer la mémoire utilisée pour contenir les classes bytecode et/ou code natif.

Réglage de CMSClassUnloadingEnabled pourrait aider avec votre permgen problème si vous êtes actuellement en utilisant le CMS collector . Mais les chances sont que vous n'utilisez pas le CMS, ou que vous avez une véritable fuite de mémoire liée à classloader. Dans ce dernier cas, votre classe ne semblera jamais inutilisée au CA ... et ne sera donc jamais être déchargement.


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

En fait, c'est ce qui se passe quand vous faites une chaude redéployer d'une webapp. (Ou du moins, c'est ce qui devrait se passer, si vous pouvez éviter les problèmes qui conduisent à une fuite de stockage de permgen.)

35
répondu Stephen C 2015-09-28 22:16:03

un exemple où cela est utile:

paramétrage -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled sur notre Weblogic 10.3 JVM a aidé à résoudre un problème où l'implémentation de JAX-WS a créé une nouvelle classe de proxy pour chaque appel de service web, conduisant éventuellement à des erreurs de mémoire.

ce n'était pas anodin à tracer. Le code suivant renvoie toujours la même classe de proxy pour 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);

à L'interne, ce mandataire délégué à une instance de weblogic.wsee.jaxws.spi.ClientInstance , qui à nouveau délégué à une nouvelle classe $Proxy[nnnn]n a été incrémenté à chaque appel. En ajoutant les drapeaux, n était encore incrémenté, mais au moins ces classes temporaires ont été retirées de la mémoire.

sur une note plus générale, cela peut être très utile pour faire un usage intensif de Java reflection et de proxies à travers java.lang.reflect.Proxy

24
répondu Lukas Eder 2012-11-12 10:39:36