Pertanyaan Berurusan dengan kesalahan "java.lang.OutOfMemoryError: PermGen space"


Baru-baru ini saya mengalami kesalahan ini dalam aplikasi web saya:

java.lang.OutOfMemoryError: PermGen space

Ini adalah aplikasi Hibernate / JPA + IceFaces / JSF yang berjalan pada Tomcat 6 dan JDK 1.6. Rupanya ini dapat terjadi setelah menerapkan ulang aplikasi beberapa kali.

Apa penyebabnya dan apa yang bisa dilakukan untuk menghindarinya? Bagaimana cara saya memperbaiki masalah?


1178
2017-09-18 03:29


asal


Jawaban:


Solusinya adalah menambahkan bendera ini ke baris perintah JVM ketika Tomcat dimulai:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Anda dapat melakukannya dengan mematikan layanan tomcat, lalu masuk ke direktori Tomcat / bin dan menjalankan tomcat6w.exe. Di bawah tab "Java", tambahkan argumen ke kotak "Java Options". Klik "OK" dan kemudian restart layanan.

Jika Anda mendapatkan kesalahan layanan yang ditentukan tidak ada sebagai layanan yang diinstal Anda harus menjalankan:

tomcat6w //ES//servicename

dimana Nama layanan adalah nama server yang dilihat di services.msc

Sumber: komentar orx di Jawaban Eric yang lincah.


549
2017-09-17 22:23



Anda lebih baik mencoba -XX:MaxPermSize=128M daripada -XX:MaxPermGen=128M.

Saya tidak bisa mengatakan penggunaan tepat dari kolam memori ini, tetapi ada hubungannya dengan jumlah kelas yang dimuat ke JVM. (Dengan demikian memungkinkan pembongkaran kelas untuk tomcat dapat menyelesaikan masalah.) Jika aplikasi Anda menghasilkan dan mengkompilasi kelas saat dijalankan, lebih mungkin membutuhkan memori yang lebih besar dari default.


247
2017-09-18 02:09



Kesalahan server App PermGen yang terjadi setelah beberapa penerapan kemungkinan besar disebabkan oleh referensi yang dipegang oleh penampung ke kelas kelas aplikasi lama Anda. Misalnya, menggunakan kelas tingkat log khusus akan menyebabkan referensi dipegang oleh kelas server aplikasi. Anda dapat mendeteksi kebocoran inter-classloader ini dengan menggunakan alat analisis JVM modern (JDK6 +) seperti jmap dan jhat untuk melihat kelas yang terus diadakan di aplikasi Anda, dan mendesain ulang atau menghilangkan penggunaannya. Tersangka yang biasa adalah database, penebang, dan pustaka tingkat-kerangka kerja tingkat lainnya.

Lihat Classloader bocor: pengecualian "java.lang.OutOfMemoryError: PermGen space", dan terutama posting tindak lanjut.


152
2018-03-11 22:24



Kesalahan umum yang orang lakukan adalah berpikir bahwa tumpukan ruang dan ruang permgen adalah sama, yang sama sekali tidak benar. Anda bisa memiliki banyak ruang yang tersisa di tumpukan tetapi masih bisa kehabisan memori di permgen.

Penyebab umum OutofMemory di PermGen adalah ClassLoader. Setiap kali kelas dimuat ke JVM, semua data meta, bersama dengan Classloader, disimpan di area PermGen dan mereka akan menjadi sampah dikumpulkan ketika Classloader yang memuat mereka siap untuk pengumpulan sampah. Dalam Kasus Classloader memiliki kebocoran memori dari semua kelas yang dimuat olehnya akan tetap dalam memori dan menyebabkan permGen outofmemory setelah Anda mengulanginya beberapa kali. Contoh klasiknya adalah Java.lang.OutOfMemoryError: PermGen Space di Tomcat.

Sekarang ada dua cara untuk menyelesaikan ini:
1. Temukan penyebab Memory Leak atau jika ada kebocoran memori.
2. Menambah ukuran PermGen Space dengan menggunakan parameter JVM -XX:MaxPermSize dan -XX:PermSize.

Anda juga bisa memeriksanya 2 Solusi Java.lang.OutOfMemoryError di Jawa untuk lebih jelasnya.


65



Gunakan parameter baris perintah -XX:MaxPermSize=128m untuk Sun JVM (jelas mengganti 128 untuk ukuran apa pun yang Anda butuhkan).


39



Mencoba -XX:MaxPermSize=256m dan jika terus berlanjut, cobalah -XX:MaxPermSize=512m


35



saya ditambahkan  -XX: MaxPermSize = 128m (Anda dapat bereksperimen mana yang terbaik) Argumen VM karena saya menggunakan ide gerhana. Di sebagian besar JVM, default PermSize sekitar 64 MB yang kehabisan memori jika ada terlalu banyak kelas atau sejumlah besar String dalam proyek.

Untuk gerhana, itu juga dijelaskan di menjawab.

LANGKAH 1 : Klik ganda pada server tomcat di Server Tab

enter image description here

LANGKAH 2 : Buka peluncuran Conf dan tambahkan -XX: MaxPermSize = 128m sampai akhir yang ada Argumen VM.

enter image description here


24



Saya telah menyerempet kepalaku terhadap masalah ini saat menyebarkan dan menerapkan aplikasi web yang rumit juga, dan berpikir saya akan menambahkan penjelasan dan solusi saya.

Ketika saya menyebarkan aplikasi di Apache Tomcat, ClassLoader baru dibuat untuk aplikasi itu. ClassLoader kemudian digunakan untuk memuat semua kelas aplikasi, dan pada undeploy, semuanya harus pergi dengan baik. Namun, pada kenyataannya itu tidak sesederhana itu.

Satu atau lebih dari kelas yang dibuat selama kehidupan aplikasi web memegang referensi statis yang, di suatu tempat di sepanjang garis, referensi ClassLoader. Karena referensi awalnya statis, tidak ada jumlah pengumpulan sampah yang akan membersihkan referensi ini - ClassLoader, dan semua kelas yang dimuatnya, akan tetap ada di sini.

Dan setelah beberapa redeploys, kita menemukan OutOfMemoryError.

Sekarang ini telah menjadi masalah yang cukup serius. Saya dapat memastikan bahwa Tomcat di-restart setelah setiap redeploy, tetapi yang menghapus seluruh server, bukan hanya aplikasi yang dipekerjakan ulang, yang sering tidak layak.

Jadi, bukannya saya telah menyusun solusi dalam kode, yang bekerja pada Apache Tomcat 6.0. Saya belum menguji pada server aplikasi lain, dan harus menekankan hal itu ini sangat mungkin untuk tidak bekerja tanpa modifikasi pada server aplikasi lainnya.

Saya juga ingin mengatakan bahwa secara pribadi saya membenci kode ini, dan itu tidak ada yang harus menggunakan ini sebagai "perbaikan cepat" jika kode yang ada dapat diubah untuk menggunakan metode shutdown dan pembersihan yang tepat. Satu-satunya waktu ini harus digunakan adalah jika ada perpustakaan eksternal kode Anda tergantung pada (Dalam kasus saya, itu adalah klien RADIUS) yang tidak menyediakan sarana untuk membersihkan referensi statis sendiri.

Pokoknya, lanjutkan dengan kode. Ini harus dipanggil pada titik di mana aplikasi tidak digunakan - seperti metode menghancurkan servlet atau (pendekatan yang lebih baik) metode contextDestroyed ServletContextListener.

//Get a list of all classes loaded by the current webapp classloader
WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
Field classLoaderClassesField = null;
Class clazz = WebappClassLoader.class;
while (classLoaderClassesField == null && clazz != null) {
    try {
        classLoaderClassesField = clazz.getDeclaredField("classes");
    } catch (Exception exception) {
        //do nothing
    }
    clazz = clazz.getSuperclass();
}
classLoaderClassesField.setAccessible(true);

List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));

for (Object o : classes) {
    Class c = (Class)o;
    //Make sure you identify only the packages that are holding references to the classloader.
    //Allowing this code to clear all static references will result in all sorts
    //of horrible things (like java segfaulting).
    if (c.getName().startsWith("com.whatever")) {
        //Kill any static references within all these classes.
        for (Field f : c.getDeclaredFields()) {
            if (Modifier.isStatic(f.getModifiers())
                    && !Modifier.isFinal(f.getModifiers())
                    && !f.getType().isPrimitive()) {
                try {
                    f.setAccessible(true);
                    f.set(null, null);
                } catch (Exception exception) {
                    //Log the exception
                }
            }
        }
    }
}

classes.clear();

22



Alternatif lain, Anda dapat beralih ke JRockit yang menangani permgen secara berbeda dari jvm matahari. Secara umum memiliki kinerja yang lebih baik juga.

http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html


15