Cosa causa PermGen OutOfMemoryError su JBoss?


8

Qual è la causa di un PermGen OutOfMemoryError in JBoss?

Sto eseguendo JBoss AS 4.2.2 nel mio ambiente di sviluppo e ciò si verifica dopo aver ridistribuito la mia applicazione Web un gran numero di volte.

Il blog di Christian Vest Hansen offre opzioni JVM che aiutano molto , ma non risolvono completamente il problema:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m

Risposte:


5

Come già accennato, probabilmente stai riscontrando caricatori di classi che perdono. Per qualche motivo le tue classi non vengono scaricate. Questo può accadere per due motivi

  • Gli oggetti di dette classi esistono ancora nell'heap, gli oggetti fanno sempre riferimento alla loro classe o
  • Il caricatore di classi fa riferimento da qualche parte, per qualsiasi motivo, i caricatori di classi fanno riferimento alle loro classi per non caricarle due volte

Non esiste una soluzione globale a questo problema. Uno strumento utile per aiutarti a trovare la causa principale è lo strumento Analizzatore di memoria Eclipse , che puoi applicare a un dump dell'heap dalla tua JVM (puoi abilitare i dump dell'heap su OOM con l'opzione -XX: + HeapDumpOnOutOfMemoryError). Forse inizia a cercare oggetti java.lang.Class dalla tua app web per capire perché vengono mantenuti in vita. Sfortunatamente, PermGen non fa normalmente parte di un dump di heap JVM, quindi puoi solo provare a trovare artefatti correlati nel resto dell'heap (gli oggetti di classe non sono memorizzati in PermGen se non sbaglio, solo il vero codice byte è, per favore correggimi se sbaglio però).

HTH.

Modifica:
Dave Cheney suggerisce in un commento che java.lang.Class-object fa effettivamente parte di PermGen e non è incluso in una normale discarica di hotspot. A meno che tu non abbia una JVM che scrive queste informazioni nella discarica dell'heap, avrai bisogno di un approccio diverso. Puoi ancora cercare le istanze dei tuoi oggetti, ma se perdi classi / caricatori di classi (entrambi purtroppo si implicano reciprocamente) sembra che tu debba cercare altri segni (oggetti meta-dati di JBoss, ecc.).


1
Sono abbastanza certo che gli oggetti Class siano archiviati in PermGen (ovvero, oggetti che sono istanze di Class). C'è un'area separata su Sun JVM chiamata Code Cache, in cui è memorizzato il codice che è stato compilato per il codice macchina. Sia PermGen che Code Cache fanno parte della memoria Non Heap che puoi vedere usando strumenti come jconsole
Dave Cheney,

@Dave Cheney: hai ragione. Gli oggetti Class trapelati bloccati in PermGen sono di solito la causa del problema del PO.
Eddie,

uova, anche se non credo che i contenuti di PermGen siano scritti nella discarica dell'heap (questo utilizza Sun JVM, non ho molta esperienza con gli altri), il formato della discarica hprof sicuramente conosce cose come, quante classi caricate, quanti caricatori di classi, ecc. Puoi vederlo quando apri hprof in Eclipse Memory Analyzer). Ciò che probabilmente non è scritto sono i grandi dati della classe binaria che compongono il codice byte java, ciò che vedi nel dump dell'heap è lo 'stub' dell'istanza Class memorizzata su PermGen.
Dave Cheney,

2

La causa sottostante sono riferimenti a classi che sono state scartate che perdono al di fuori del loro classloader, impedendo alla JVM di scaricare quelle classi dal permesso. I flag che usi possono far sì che la JVM elimini in modo aggressivo le classi che sono scaricabili, ma non risolverà il problema sottostante.

C'è una spiegazione valida e complessa qui


1

La causa dell'errore PermGen OutOfMemory è l'app ridistribuzione. La causa sottostante sono gli oggetti Class trapelati in PermGen dai ridistribuzioni.

Naturalmente, la soluzione alternativa è riavviare la JVM dopo un certo numero di ridistribuzioni.

Questo è un problema molto difficile da risolvere totalmente, anche se con qualche indovinello puoi spesso apportare grandi miglioramenti. Ecco da dove iniziare: quando l'app Web viene arrestata, assicurarsi che:

  • tutti i thread che hai iniziato vengono interrotti
  • tutti i ThreadPool che hai avviato vengono chiusi
  • vengono rilasciati tutti i riferimenti statici che è possibile rilasciare

Queste sono alcune delle cose che possono causare l'intrappolamento di un oggetto Class in PermGen.

Inoltre, si noti che non tutte le JVM (o tutte le versioni di JVM) eseguiranno gli oggetti della classe GC in PermGen. Se si sta eseguendo una JVM o una versione di una JVM che non oggetti della classe GC in PermGen, l'unica scelta è riavviare la JVM dopo un certo numero di ridistribuzioni. Questo probabilmente non si applica a te, date le opzioni JVM che menzioni.

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.