web-dev-qa-db-fra.com

Que fait réellement la JVM Flag CMSClassUnloadingEnabled?

Je ne peux pas pour toute la vie trouver une définition de ce que fait réellement le drapeau Java VM CMSClassUnloadingEnabled, mis à part certaines définitions très floues de haut niveau telles que "gets débarrassez-vous de vos problèmes de PermGen "( ce qui n'est pas le cas , d'ailleurs).

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.

En fonction du nom de l'indicateur, je suppose que le récupérateur de place CMS ne décharge pas les classes par défaut, et cet indicateur l'activera, mais je ne peux pas en être sûr.

180
Rich

Update Cette réponse est pertinente pour Java 5-7, Java 8 a ceci corrigé: https://blogs.Oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Félicitations à mt.uul =

Pour Java 5-7:

Le look standard Oracle/Sun VM sur le monde est le suivant: les classes sont éternelles. Ainsi, une fois chargées, elles restent en mémoire même si plus personne ne s'en soucie. Ce n'est généralement pas un problème avoir autant de classes purement "setup" (= utilisé une fois pour l’installation et plus jamais). Ainsi, même s’ils occupent 1 Mo, peu importe.

Mais récemment, nous avons des langages comme Groovy, qui définissent les classes au moment de l’exécution. Chaque fois que vous exécutez un script, une (ou plusieurs) nouvelle classe est créée et reste en permanence dans PermGen. Si vous utilisez un serveur, cela signifie que vous avez une fuite de mémoire.

Si vous activez CMSClassUnloadingEnabled, le CPG balayera également PermGen et supprimera les classes qui ne sont plus utilisées.

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

214
Aaron Digulla

Selon l'article de blog La liste la plus complète d'options -XX pour Java JVM , elle détermine si le déchargement de classe est activé sous le récupérateur de mémoire CMS. Le paramètre par défaut est false. Il existe une autre option appelée ClassUnloading qui est true par défaut et qui affecte (vraisemblablement) les autres éboueurs.

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

La définition de CMSClassUnloadingEnabled pourrait aider à résoudre votre problème de permgen si vous utilisez actuellement le collecteur CMS . Mais il est probable que vous n'utilisez pas le CMS ou que vous avez une fuite de mémoire liée au chargeur de classes. Dans ce dernier cas, votre classe ne semblera jamais être inutilisée par le GC ... et ne sera donc jamais déchargée.


Aaron Digulla dit que "les cours sont pour toujours". Ce n’est pas tout à fait vrai, même dans le monde pur Java. En fait, la durée de vie d’une classe est liée à son chargeur de classes. Donc, si vous pouvez organiser qu’un chargeur de classes est nettoyé (et n’est pas toujours facile à faire), les classes qu’il a chargées seront également récupérées.

En fait, c'est ce qui se produit 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 permgen.)

35
Stephen C

Un exemple où cela est utile:

Réglage -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled sur notre machine virtuelle Java Weblogic 10.3 a aidé à résoudre un problème où l'implémentation de JAX-WS créait une nouvelle classe de proxy pour chaque appel de service Web, aboutissant éventuellement à des erreurs de mémoire insuffisante.

Ce n'était pas trivial à tracer. Le code suivant a toujours renvoyé 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);

En interne, ce proxy délégué à une instance de weblogic.wsee.jaxws.spi.ClientInstance, qui a de nouveau délégué à un nouveau $Proxy[nnnn] classe où n a é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.

Sur une note plus générale, cela peut être très utile lorsque vous utilisez beaucoup Java réflexion et proxy au travers de Java.lang.reflect.Proxy

24
Lukas Eder