Cosa fa effettivamente JVM flag CMSClassUnloadingEnabled?


183

Per la vita non riesco a trovare una definizione di ciò che CMSClassUnloadingEnabledeffettivamente fa il flag Java VM , oltre ad alcune definizioni di alto livello molto sfocate come "sbarazzarsi dei tuoi problemi PermGen" ( che non lo fa , tra l'altro).

Ho guardato sul sito di Sun / Oracle, e anche l'elenco delle opzioni non dice proprio quello che fa.

In base al nome del flag, suppongo che CMS Garbage Collector non scarichi le classi per impostazione predefinita e questo flag lo attiva, ma non posso esserne sicuro.

Risposte:


219

Aggiornamento Questa risposta è rilevante per Java 5-7, Java 8 ha risolto questo problema: https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos go to mt. Uulu

Per Java 5-7:

L'aspetto standard di Oracle / Sun VM sul mondo è: le classi sono per sempre. Quindi, una volta caricati, rimangono in memoria anche se a nessuno importa più. Questo di solito non è un problema dato che non hai molte classi puramente di "setup" (= usato una volta per l'installazione e poi mai più). Quindi, anche se occupano 1 MB, chi se ne frega.

Ma ultimamente, abbiamo lingue come Groovy, che definiscono le classi in fase di esecuzione. Ogni volta che esegui uno script, vengono create una (o più) nuove classi che rimangono in PermGen per sempre. Se stai eseguendo un server, significa che hai una perdita di memoria.

Se si abilita CMSClassUnloadingEnabledil GC, spazzerà anche PermGen e rimuoverà le classi che non vengono più utilizzate.

[EDIT] Dovrai anche abilitare UseConcMarkSweepGC(grazie a Sam Hasler ). Vedi questa risposta: https://stackoverflow.com/a/3720052/2541


17
Secondo stackoverflow.com/a/3720052/2541 per CMSClassUnloadingEnabledavere qualche impatto, UseConcMarkSweepGCdeve essere impostato anche
Sam Hasler

1
Non sono sicuro di come ciò influisca sull'idea di utilizzare UseConcatSweepGC, ma sembra che ci sia stato un bug risolto di recente in CMSClassUnloadingEnabled. È stato osservato come risolto qui: bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000325
Bill Rosmus,

3
@ Kevin: Sì, sicuramente. Vedi in fondo a groovy.codehaus.org/Running : "Groovy crea classi in modo dinamico, ma la VM Java predefinita non GC il PermGen. Se si utilizza Java 6 o versione successiva, è necessario aggiungere -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC." UseConcMarkSweepGCPer abilitare CMSClassUnloadingEnabled. "
Aaron Digulla,

1
Un buon articolo sull'utilizzo di UseConcMarkSweepGC e CMSClassUnloadingEnabled insieme. blog.redfin.com/devblog/2012/06/…
Victor

1
non più valido per 1.8: blogs.oracle.com/poonam/…
mt.uulu il

35

Secondo il post del blog L'elenco più completo di -XX opzioni per Java JVM , determina se lo scaricamento di classe è abilitato nel Garbage Collector CMS. L'impostazione predefinita è false. C'è un'altra opzione chiamata ClassUnloadingche è truedi default che (presumibilmente) influenza gli altri garbage collector.

L'idea è che se il GC rileva che una classe precedentemente caricata non viene più utilizzata da nessuna parte nella JVM, può recuperare la memoria utilizzata per contenere le classi bytecode e / o codice nativo.

L'impostazione di CMSClassUnloadingEnabled potrebbe aiutare a risolvere il problema con Permgen se stai attualmente utilizzando il raccoglitore CMS . Ma è probabile che non si stia utilizzando il CMS o che si disponga di una perdita di memoria relativa al classloader autentico. In quest'ultimo caso, la tua classe non sembrerà mai inutilizzata al GC ... e quindi non verrà mai scaricata.


Aaron Digulla afferma che "le lezioni sono per sempre". Questo non è strettamente vero, anche nel mondo puramente Java. In effetti, la durata di una classe è legata al suo caricatore di classi. Quindi, se puoi organizzare che un classloader sia garbage collection (e che non sia sempre una cosa facile da fare), anche le classi caricate saranno garbage collection.

In effetti, questo è ciò che accade quando si esegue una ridistribuzione a caldo di una webapp. (O almeno, è quello che dovrebbe succedere, se puoi evitare i problemi che portano a una perdita di conservazione del permgen.)


24

Un esempio in cui questo è utile:

Ambientazione -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled sul nostro Weblogic 10.3 JVM ha aiutato a risolvere un problema in cui l'implementazione di JAX-WS ha creato una nuova classe proxy per ogni chiamata del servizio Web, causando infine errori di memoria insufficiente.

Non è stato banale da rintracciare. Il seguente codice ha sempre restituito la stessa classe proxy perport

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);

Internamente, questo proxy è stato delegato a un'istanza di weblogic.wsee.jaxws.spi.ClientInstance, che ha nuovamente delegato a una nuova $Proxy[nnnn]classe dove è nstata incrementata ad ogni chiamata. Quando si aggiungevano i flag, nveniva comunque incrementato, ma almeno quelle classi temporanee venivano rimosse dalla memoria.

Su una nota più generale, questo può essere molto utile quando si fa un uso intenso della riflessione e dei proxy Java java.lang.reflect.Proxy


+1 per condividere esperienze reali. Abbiamo anche riscontrato questo problema su torquebox in cui il server ha generato un numero enorme di classi a causa dei processi di compilazione di JRuby.
Nurettin,

7
nota anche che -XX:+CMSPermGenSweepingEnabledè deprecato a favore di-XX:+CMSClassUnloadingEnabled
nurettin

3
Una vera soluzione per questo problema è però quella di creare una volta la porta e riutilizzarla. Ecco come dovrebbe essere usato JAX-WS. La porta è anche sicura al 100%.
Rustyx,

@rustyx: puoi sostenere questa affermazione con qualche link autorevole? Sono sempre stato molto diffidente nel riutilizzare proxy e stub dei servizi Web ... Ad esempio, vedere le dichiarazioni di non responsabilità di Apache CXF . O questa domanda
Lukas Eder,

1
@rukavitsya: come ho detto nella mia risposta. Ogni volta che ho chiamato la logica di cui sopra, è stato creato un nuovo proxy
Lukas Eder il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.