2009-07-14 17 views
22

Abbiamo un'applicazione Web che utilizza Spring-Hibernate per mantenere i dati degli utenti registrati nel database Oracle. L'applicazione funziona bene in ambiente di sviluppo, ma quando lo copiamo in ambiente live con molti più dati, non è riuscito. Inizialmente l'applicazione si avvia normalmente, ma dopo poche azioni si è verificata l'eccezione "PermGen out of space".Cosa si può fare con l'eccezione "PermGen fuori dallo spazio" nell'applicazione Web Tomcat-Spring-Hibernate?

Ho iniziato a cercare nei forum di Google, Spring e Hibernate, ma non aiuta. Ci sono molte discussioni su questo errore, ma per ogni soluzione ci sono persone che dicono: "Funziona" e altre persone dicono "Non funziona".

Ad esempio, molte persone offrono di aumentare il parametro JVM -XX:MaxPermSize, altri dicono che non funziona. Ci sono post che dicono che è necessario utilizzare il problema dell'uso della libreria javassist e di altri e della libreria cglib. Altri dicono che il problema è in cgl.

Utilizziamo Java1.5_0_09, Spring 2.5 con javaassist3.4.GA, Tomcat 5.5 come web-container e Oracle 10g come database.

Qualcuno può spiegarmi che cosa causa questo problema e come risolverlo?

+1

Sei un tirocinante() con un sacco di stringhe? Stringhe internate live in PermGen – bajafresh4life

risposta

19

Il -XX:MaxPermSize funziona, devi solo ottenere il giusto valore. L'impostazione predefinita, credo, è 32mb per la VM in modalità client e 64mb per la VM in modalità server. Suggerisco impostandolo a 256mb, se avete la memoria:

java -XX:MaxPermSize=256m 

Il problema si verifica perché la primavera e Hibernate possono fare uso pesante di classi di runtime generati, a volte molti di loro. Queste classi generate passano tutte nel pool di memoria PermGen, quindi se si utilizzano tali framework, è spesso necessario aumentare il PermGen in grandi quantità.

+11

E sappiate che questo ritarda solo il problema. Se la tua applicazione genera regolarmente delle lezioni, dovrai riavviare il tuo server di tanto in tanto. – Stroboskop

+0

Purtroppo, sì. Sembra che siamo praticamente bloccati con esso. – skaffman

+0

@skaffman, questo significa che qualsiasi applicazione creata su Spring e Hibernate deve essere riavviata per impedire a OOM di PermGen? Voglio il mio server per sempre a meno che non spinga un nuovo codice. –

3

Come skaffman dice che la proprietà -XX: MaxPermSize funziona, tuttavia a volte è possibile che si verifichi un problema di fondo che aumentando il limite può solo differire.

Hai visto this note? Mi ha aiutato a risolvere un problema simile una volta. per riassumere il link:

  • driver JDBC Mettere in comune/lib (come dice tomcat documentation) e non in WEB-INF/lib
  • non mettere commons-logging in WEB-INF/lib dal tomcat già lo bootstraps
4

Ho visto questo problema con Hibernate (usato senza Spring). Il problema era che stavamo creando un'istanza di SessionFactory per ogni richiesta utente invece di creare una singola istanza per la durata dell'applicazione.

Ho utilizzato il YourKit profiler per indagare su questo e scoprire il problema.

8

È necessario essere consapevoli del fatto che alcune versioni di Tomcat hanno perdite di memoria sulla ridistribuzione della guerra. Mi è successo su tomcat 6.0.x.

Come suggerito aumentare la MaxPermSize, questa è una soluzione temporanea per la vostra macchina di sviluppo - e quando si ottiene l'errore, dopo 2-3 giorni, basta riavviare il server. Sulla produzione non è così semplice. Quindi questo funziona per lo sviluppo, ma questo approccio non funziona per la produzione, dove è necessario risolvere i problemi relativi alle perdite di memoria.

Per scoprire le perdite utilizzare l'applicazione jconsole fornita con jdk 1.6 e 1.5. È possibile associare a un processo e guardare la memoria utilizzata nel tempo.

Si può anche leggere questi:

2

visiva GC, ora parte di JDK 6, fornisce una rappresentazione grafica molto bella della memoria in tempo reale. Puoi vedere cosa succede agli spazi eden, generazionali e perm. Non capirai perché.

AGGIORNAMENTO: È bin/jvisualvm.exe nella distro JDK 1.6.0_13. Dagli il PID del processo che vuoi monitorare.

+1

È interessante. Il pool PermGen è notoriamente opaco e non visibile all'interfaccia di debug JVMTI. Mi chiedo come Vidual GC dia un'occhiata in là? – skaffman

0

Tutte le risposte qui riguardano il problema PermGen che si verifica a causa di diversi riavvii dell'applicazione Web, ma in questo caso il problema si verifica già alla prima distribuzione dopo il riavvio di Tomcat, quindi non può essere il problema dei riferimenti o dei commons di ClassLoader -registrazione.

+0

Questa non è una risposta, è necessario modificare la domanda originale e aggiungere questa informazione. –

0

Se si utilizza jdk6, è possibile utilizzare l'app jconsole per monitorare l'utilizzo della memoria dell'applicazione e approfondire ulteriormente.

Un'altra strada da seguire è utilizzare un profiler, io uso JProfiler e dare un'occhiata all'applicazione con quello. Ti dirà esattamente da dove viene il problema.

0

Ho eseguito lo stesso problema e ho read that Tomcat è il colpevole in questa situazione.

Poi sono passato al molo invece e tutto è andato alla grande, e l'app distribuisce/gira come previsto. Quindi se Tomcat non è un must, allora suggerirei Jetty.

Problemi correlati