2011-09-13 11 views
19

So che questo non è "best practice", ma vorrei sapere se posso riavvio automatico Tomcat se la mia app schierato genera un'eccezione OutOfMemoryPosso riavvio automatico Tomcat JVM su di un'eccezione di memoria

+0

La risposta corretta è che gli autori di Java non dovrebbero mai hanno fatto OutOfMemoryErrors catturabile. Dovrebbero sempre uccidere la VM e uno script o un manager gestiscono il riavvio. Inoltre, Tomcat non dovrebbe catturare neanche questi. – mikevdg

risposta

23

Si può provare a utilizzare l'opzione OnOutOfMemoryError JVM

-XX:OnOutOfMemoryError="/yourscripts/tomcat-restart" 

E 'anche possibile generare l'heap dump per un'analisi successiva:

-XX:+HeapDumpOnOutOfMemoryError 

stare attenti con la combinazione di queste due opzioni. Se si forza l'eliminazione del processo in "tomcat-restart", il dump dell'heap potrebbe non essere completo.

+0

io in realtà un errore di PermGen causa di una perdita classloader credo. Sarà lo stesso lavoro di bandiera in questo scenario anche? – Abe

+2

Sì , si lavorerà per errore di spazio PermGen pure. – Dan

+0

Ma qual è il contenuto di "tomcat-restart"? e 'solo shutdown.bat, startup.bat? – Gullbyrd

5

non facilmente e sicuramente non attraverso la JVM che ha appena subito l'eccezione di memoria insufficiente. La soluzione migliore sarebbe una combinazione di monitor di stato tomcat accoppiato con script cron o script di sistema di sistema correlati correlati; qualcosa per verificare lo stato del server e arrestare e riavviare automaticamente il servizio in caso di errore.

+0

Sembra che questo è il consenso generale ... :( – Abe

4

Generalmente, n. La VM è uno stato negativo e non può essere completamente affidabile.

In genere, è possibile utilizzare un processo di wrapper configurabile che avvia e arresta la VM del server "reale" che si desidera. Un esempio con cui ho lavorato è "Java Service Wrapper" di Tanuki Software http://wrapper.tanukisoftware.com/doc/english/download.jsp

So che ce ne sono altri.

Per proteggersi dalle OOM in primo luogo, ci sono modi per strumentare le moderne macchine virtuali tramite i bean di interfaccia per interrogare lo stato dell'heap e altre strutture di memoria. Questi possono essere usati, ad esempio, per avvisare in un log o un'email se alcune operazioni specifiche dell'app stanno spingendo alcuni limiti stabiliti.

+1

involucro di Tanuki è sicuramente il modo migliore per andare –

+0

uno nel mio caso lo script è stato eseguito come parte del XX: OnOutOfMemoryError = "/ yourscripts/tomcat-restart era in grado di portare il gatto di back up – Tomasz

+0

Theres di YAJSW anche la pretesa di essere pienamente compatibile con JSW. si consiglia di fare un tentativo se si adatta alle vostre esigenze (è open source), ma dalla mia esperienza JSW vale il prezzo. –

6

So che questo non è quello che hai chiesto, ma hai provato a guardare attraverso una discarica dell'heap per vedere dove potresti perdere memoria?

Alcuni strumenti molto utili per rintracciare le perdite di memoria:

jdk/bin/jmap -histo:live pid 

questo vi darà un istogramma di tutti gli oggetti dal vivo attualmente in JVM. Cerca eventuali conteggi di oggetti dispari. Dovrai conoscere la tua applicazione abbastanza bene per essere in grado di determinare quali conteggi degli oggetti sono dispari.

jdk/bin/jmap -dump:live,file=heap.hprof pid 

Questo scaricherà l'intero heap della JVM identificato da pid. È quindi possibile utilizzare l'ottimo Eclipse Memory Analyzer per ispezionarlo e scoprire chi si aggrappa ai riferimenti dei propri oggetti. I tuoi due più grandi amici in Eclipse Memory Analyzer sono gli histo grammi e uno right click -> references -> exclude weak/soft references per vedere cosa fa riferimento al tuo oggetto.

jconsole è ovviamente un altro valido strumento.

+0

Grazie per il hprof di comando, bene avere nell'arsenale ... :) io uso VisualVM per queste cose normalmente. – Abe

0

E qualcosa di simile? -XX:OnOutOfMemoryError="exec \`ps --no-heading -p $$ -o cmd\`"

1

Sfortunatamente quando si uccide il processo java. Lo script manterrà un riferimento alle porte tomcat 8080 8005 8009 e non sarà possibile avviarlo nuovamente dallo stesso script. L'unico modo in cui funziona per me è:

-XX: OnOutOfMemoryError = "kill -9% p" e poi un altro cron o monit o qualcosa di simile per assicurare che il tomcat sia di nuovo in esecuzione.

% p è in realtà il pid JVM, qualcosa che il JVM prevede per voi.

Problemi correlati