Apa yang menyebabkan PermGen OutOfMemoryError di JBoss?

8

Apa penyebab yang mendasari PermGen OutOfMemoryError di JBoss?

Saya menjalankan JBoss AS 4.2.2 di lingkungan pengembangan saya, dan ini terjadi setelah menggunakan kembali aplikasi web saya dalam jumlah besar.

Blog Christian Vest Hansen memberikan opsi JVM yang banyak membantu , tetapi tidak menyelesaikan masalah sepenuhnya:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
Peter Hilton
sumber

Jawaban:

5

Seperti yang telah disebutkan, Anda mungkin mengalami loader kelas yang bocor. Untuk beberapa alasan, kelas Anda tidak diturunkan. Ini bisa terjadi karena dua alasan

  • Objek dari kelas tersebut masih ada di heap, objek selalu referensi kelas mereka, atau
  • Pemuat kelas direferensikan di suatu tempat, untuk alasan apa pun, pemuat kelas mereferensikan kelas mereka agar tidak memuatnya dua kali

Tidak ada solusi untuk semua masalah ini. Salah satu alat yang membantu untuk menemukan penyebab utama adalah Alat Eclipse Memory Analyzer , yang dapat Anda terapkan ke tumpukan tumpukan dari JVM Anda (Anda dapat mengaktifkan tumpukan tumpukan pada OOMs dengan opsi -XX: + HeapDumpOnOutOfMemoryError). Mungkin mulai mencari objek java.lang.Class dari aplikasi web Anda untuk melihat mengapa mereka tetap hidup. Sayangnya, PermGen biasanya bukan bagian dari tumpukan heap JVM, jadi Anda hanya dapat mencoba menemukan artefak yang berkorelasi di sisa heap (objek-Class tidak disimpan di PermGen jika saya tidak salah, hanya kode byte yang sebenarnya, tolong koreksi saya jika saya salah).

HTH.

Sunting:
Dave Cheney menyarankan dalam komentar bahwa java.lang.Class-objects memang bagian dari PermGen, dan tidak termasuk dalam dump heap hotspot normal. Kecuali Anda memiliki JVM yang menulis info ini di heap dump, Anda akan memerlukan pendekatan yang berbeda. Anda masih dapat mencari instance dari objek Anda, tetapi jika Anda membocorkan class / class loader (keduanya sayangnya menyiratkan satu sama lain) sepertinya Anda perlu mencari tanda-tanda lain (meta data object dari JBoss, dll).

Falstro
sumber
1
Saya cukup yakin bahwa objek Class disimpan dalam PermGen (yaitu, objek yang merupakan instance dari Class). Ada area terpisah di Sun JVM yang disebut Code Cache, yang merupakan tempat kode yang telah dikompilasi ke kode mesin disimpan. Baik PermGen dan Kode Cache adalah bagian dari memori Non Heap yang dapat Anda lihat menggunakan alat-alat seperti jconsole
Dave Cheney
@ Dave Cheney: Anda benar. Objek Class yang bocor yang tersangkut di PermGen biasanya merupakan penyebab masalah OP.
Eddie
roe, sementara saya tidak berpikir konten PermGen ditulis ke heap dump (ini menggunakan Sun JVM, saya tidak punya banyak pengalaman dengan yang lain), format dump hprof tentu tahu hal-hal seperti, berapa banyak kelas dimuat, berapa banyak kelas loader, dll. Anda dapat melihat ini saat membuka hprof di Eclipse Memory Analyzer). Apa yang mungkin tidak ditulis adalah data kelas biner besar yang membentuk kode byte java, apa yang Anda lihat di heap dump adalah 'stub' dari instance Class yang disimpan di PermGen.
Dave Cheney
2

Penyebab yang mendasari adalah referensi ke kelas yang telah dibuang bocor di luar classloader mereka, mencegah JVM dari membongkar kelas-kelas tersebut dari gen perm. Bendera yang Anda gunakan dapat menyebabkan JVM untuk secara agresif membersihkan kelas yang tidak dapat dibongkar, tetapi itu tidak akan menyelesaikan masalah yang mendasarinya.

Ada penjelasan yang bagus dan kompleks di sini

Dave Cheney
sumber
1

Penyebab kesalahan PermGen OutOfMemory adalah aplikasi menebus kembali. Penyebab mendasar adalah bocor objek Class di PermGen dari redeploys.

Tentu saja, solusinya adalah memulai kembali JVM setelah sejumlah redeploys.

Ini adalah masalah yang sangat sulit untuk dipecahkan secara total, walaupun dengan sedikit sleuthing Anda sering dapat melakukan perbaikan besar. Di sinilah Anda mulai: Ketika aplikasi web Anda dihentikan, pastikan bahwa:

  • semua utas yang Anda mulai dihentikan
  • semua ThreadPools yang Anda mulai dimatikan
  • semua referensi statis yang dapat Anda lepaskan dirilis

Ini adalah beberapa hal yang dapat menyebabkan objek Class terjebak di PermGen.

Juga, perhatikan bahwa tidak semua JVM (atau semua versi JVM) akan objek Kelas GC di PermGen. Jika Anda menjalankan JVM atau versi JVM yang tidak akan objek Kelas GC di PermGen, maka satu-satunya pilihan Anda adalah me-restart JVM setelah sejumlah redeploys. Ini mungkin tidak berlaku untuk Anda, mengingat opsi JVM yang Anda sebutkan.

Eddie
sumber