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

1222

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

java.lang.OutOfMemoryError: Ruang PermGen

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

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

Chris
sumber
Saya telah berjuang ini selama berjam-jam, tetapi saya tidak punya kabar baik. Lihat pertanyaan saya yang terkait: stackoverflow.com/questions/1996088/... Anda mungkin masih memiliki kebocoran memori, mis. Kelas tidak mengumpulkan sampah karena WebAppClassLoader Anda bukan sampah yang dikumpulkan (memiliki referensi eksternal yang tidak dihapus). meningkatkan PermGen hanya akan menunda OutOfMemoryError, dan mengizinkan pengumpulan sampah kelas merupakan prasyarat, tetapi tidak akan mengumpulkan sampah kelas jika loader kelas mereka masih memiliki referensi untuk itu.
Eran Medan
Saya mendapatkan kesalahan ini saat menambahkan tampilan taglib . Menghapus begitu juga memecahkan kesalahan. Kenapa begitu?
masT
Dan bagaimana Anda bertemu dengannya?
Thorbjørn Ravn Andersen
13
gunakan JDK 1.8: þ selamat datang di MetaSpace
Rytek
Jika menggunakan Windows, ikuti petunjuk ini daripada mencoba mengatur bendera secara manual di file konfigurasi. Ini dengan benar mengatur nilai-nilai dalam registri untuk dipanggil oleh Tomcat selama runtime. stackoverflow.com/questions/21104340/…
MacGyver

Jawaban:

563

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

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Anda dapat melakukannya dengan mematikan layanan tomcat, kemudian 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

di mana servicename adalah nama server seperti yang dilihat di services.msc

Sumber: komentar orx pada Eric's Agile Answers .

Chris
sumber
39
Artikel di bawah ini menyarankan -XX: + UseConcMarkSweepGC dan -XX: MaxPermSize = 128m juga. my.opera.com/karmazilla/blog/2007/03/13/…
Taylor Leese
30
-XX: + CMSPermGenSweepingEnabled Opsi ini menurunkan kinerja. Itu membuat setiap permintaan membutuhkan waktu tiga kali lebih banyak dari biasanya pada sistem kami. Gunakan dengan hati-hati.
Eldelshell
10
bekerja untuk saya - terima kasih - Saya melakukan ini di Ubuntu 10.10 dengan Tomcat6 - Saya membuat file baru: /usr/share/tomcat6/bin/setenv.sh dan menambahkan baris berikut untuk itu: JAVA_OPTS = "- Xms256m -Xmx512m - XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled "- Restarted tomcat menggunakan: sudo /etc/init.d/tomcat6 start
sami
24
Pada startup tomcat 6.0.29, dari catalina.out logfile saya: "Silakan gunakan CMSClassUnloadingEnabled sebagai pengganti CMSPermGenSweepingEnabled di masa depan"
knb
222
Pertama-tama akan sangat bagus untuk menjelaskan apa yang sebenarnya dilakukan oleh bendera-bendera ini. Hanya mengatakan: "lakukan itu dan nikmati" tidak cukup IMHO.
Nikem
251

Anda sebaiknya mencoba -XX:MaxPermSize=128Mdaripada -XX:MaxPermGen=128M.

Saya tidak bisa mengatakan dengan tepat penggunaan kumpulan memori ini, tetapi itu ada hubungannya dengan jumlah kelas yang dimuat ke JVM. (Dengan demikian mengaktifkan pembongkaran kelas untuk kucing jantan dapat menyelesaikan masalah.) Jika aplikasi Anda menghasilkan dan mengkompilasi kelas yang sedang berjalan, lebih mungkin membutuhkan kumpulan memori yang lebih besar dari standar.

toesterdahl
sumber
9
Sebenarnya, ini hanya akan menunda OOMError. Lihat jawaban di bawah ini dimulai oleh anon dengan dua tautan ke blog frankkieviet.
Rade_303
Opsi-opsi ini dijelaskan di sini: oracle.com/technetwork/java/javase/tech/…
amos
153

Server aplikasi PermGen kesalahan yang terjadi setelah beberapa penyebaran kemungkinan besar disebabkan oleh referensi yang dipegang oleh kontainer ke dalam classloader aplikasi lama Anda. Misalnya, menggunakan kelas tingkat log kustom akan menyebabkan referensi ditahan oleh classloader server aplikasi. Anda dapat mendeteksi kebocoran antar-kelas ini dengan menggunakan alat analisis JVM (JDK6 +) modern seperti jmap dan jhat untuk melihat kelas mana yang terus diadakan di aplikasi Anda, dan mendesain ulang atau menghilangkan penggunaannya. Tersangka yang biasa adalah basis data, penebang, dan pustaka tingkat dasar kerangka kerja lainnya.

Lihat kebocoran Classloader: pengecualian "java.lang.OutOfMemoryError: PermGen space" yang ditakuti , dan terutama posting tindak lanjutnya .

anon
sumber
3
Ini hanya solusi yang benar untuk masalah ini, dalam beberapa kasus mampu melakukannya terlalu sulit untuk diterapkan.
Rade_303
Sumber lain yang sangat bagus adalah people.apache.org/~markt/presentations/… (dari manajer rilis Tomcat !!).
gavenkoa
22
Sementara ini secara teoritis dapat menjawab pertanyaan, akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
Joachim Sauer
68

Kesalahan umum yang dilakukan orang 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 dapat kehabisan memori di permgen.

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

Sekarang ada dua cara untuk mengatasi ini:
1. Temukan penyebab Memory Leak atau jika ada kebocoran memori.
2. Meningkatkan ukuran Ruang PermGen dengan menggunakan param -XX:MaxPermSizedan JVM -XX:PermSize.

Anda juga dapat memeriksa 2 Solusi Java.lang.OutOfMemoryError di Java untuk detail lebih lanjut.

Peter
sumber
3
Bagaimana cara melewati param -XX:MaxPermSize and -XX:PermSize?? Saya tidak dapat menemukan catalina.bat. Versi tomcat saya adalah 5.5.26.
Deckard
Bagaimana menemukan kebocoran memori loader kelas? Apakah Anda merekomendasikan alat apa pun?
Amit
@amit untuk rekomendasi alat, lihat jawaban wiki komunitas pada pertanyaan ini.
Barett
@Deckard masuk ke direktori Tomcat / bin dan menjalankan tomcat6w.exe. Di bawah tab "Java", tambahkan argumen ke kotak "Java Options". Klik "OK"
Zeb
43

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

pengguna17163
sumber
9
Satu-satunya masalah adalah Anda hanya menunda hal yang tak terhindarkan - pada titik tertentu Anda juga akan kehabisan ruang kepala di sana. Ini solusi pragmatis yang bagus, tetapi tidak menyelesaikannya secara permanen.
Tim Howland
hal yang sama terjadi di Eclipse dan setiap kali Anda memiliki banyak pemuatan kelas dinamis. classloader tidak dibuang dan hidup dalam generasi permanen untuk selamanya
Matt
1
Saya kehabisan PermGen ketika menjalankan pekerjaan Hudson yang sangat besar ... ini memperbaikinya bagi saya.
HDave
10
@TimHowland, ini bisa menjadi perbaikan permanen jika akar penyebabnya bukan kebocoran classloader, terlalu banyak kelas / data statis di aplikasi web Anda.
Péter Török
mendapat masalah yang sama dengan HDave ketika membangun jenkins / hudson dari sumber.
louisgab
38

Coba -XX:MaxPermSize=256mdan jika terus, coba-XX:MaxPermSize=512m

bassis
sumber
56
dan jika masih bertahan coba XX:MaxPermSize=1024m:)
igo
38
dan jika masih bertahan coba XX: MaxPermSize = 2048m :)
Thomas
16
Dan jika MASIH masih ada, pikirkan kembali aplikasi Anda !! Atau coba XX: MaxPermSize = 4096m :)
Jonathan Airey
17
Anda juga dapat mencoba 8192 m tetapi sedikit berlebihan
Jacek Pietal
12
Memang berlebihan - 640KB seharusnya cukup untuk siapa pun!
Joel Purra
28

Saya menambahkan -XX: MaxPermSize = 128m (Anda dapat melakukan percobaan yang paling berhasil) ke Argumen VM karena saya menggunakan ide gerhana. Di sebagian besar JVM, PermSize default adalah sekitar 64MB yang kehabisan memori jika ada terlalu banyak kelas atau sejumlah besar String dalam proyek.

Untuk gerhana, itu juga dijelaskan pada jawaban .

LANGKAH 1 : Klik dua kali pada tomcat server di Servers Tab

masukkan deskripsi gambar di sini

LANGKAH 2 : Buka luncurkan Conf dan tambahkan -XX: MaxPermSize = 128mke akhir argumentasi VM yang ada .

masukkan deskripsi gambar di sini

prayagupd
sumber
1
Terima kasih atas jawaban terinci terbaik Anda (Catatan: klik "Buka konfigurasi peluncuran" untuk membuka "edit konfigurasi" jendela ... tapi saya menggunakan parameter berikut: "-XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled"
Chris Sim
23

Saya telah membenturkan kepala saya terhadap masalah ini saat menggunakan dan tidak menggunakan 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 saat tidak bekerja, semuanya seharusnya hilang dengan baik. Namun, pada kenyataannya itu tidak sesederhana itu.

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

Dan setelah beberapa penukaran, kami menemukan OutOfMemoryError.

Sekarang ini telah menjadi masalah yang cukup serius. Saya bisa memastikan bahwa Tomcat di-restart setelah setiap pemindahan, tetapi itu menurunkan seluruh server, bukan hanya aplikasi yang dipindah, yang seringkali tidak layak.

Jadi alih-alih saya telah mengumpulkan solusi dalam kode, yang berfungsi pada Apache Tomcat 6.0. Saya belum menguji pada server aplikasi lain, dan harus menekankan bahwa ini sangat mungkin tidak berfungsi tanpa modifikasi pada server aplikasi lain .

Saya juga ingin mengatakan bahwa secara pribadi saya benci kode ini, dan bahwa 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 saat ini harus digunakan adalah jika ada perpustakaan eksternal yang bergantung pada kode Anda (Dalam kasus saya, itu adalah klien RADIUS) yang tidak menyediakan sarana untuk membersihkan referensi statisnya sendiri.

Bagaimanapun, lanjutkan dengan kode. Ini harus disebut pada titik di mana aplikasi tidak dipekerjakan - seperti metode penghancuran servlet atau (pendekatan yang lebih baik) metode konteksDestroyed 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();
Edward Torbett
sumber
Saya tahu sudah lebih dari 8 tahun sejak saya menulis ini, tetapi di suatu tempat antara saat itu dan sekarang saya menemukan akar penyebab dan solusi yang lebih dalam. Ini adalah bahwa sementara semua kelas dalam aplikasi web dimiliki oleh classloader konteks, utas yang meminta startup dan shutdown callback dimiliki oleh induk classloader. Ini berarti bahwa jika kode shutdown menginisialisasi variabel thread-local, ini akan menyebabkan classloader induk akhirnya memegang referensi ke classloader konteks, mencegah pembersihan yang baik.
Edward Torbett
Untungnya, ada perbaikan yang sangat sederhana - pindahkan semua kode yang saat ini dalam metode shutdown ke metode menjalankan objek Thread baru. Kemudian dalam metode shutdown, mulai utas ini dan tunggu sampai selesai. Kode pembersihan akan dieksekusi secara identik, tetapi setiap variabel thread-lokal akan tetap terikat pada classloader konteks alih-alih bocor.
Edward Torbett
20

The java.lang.OutOfMemoryError: PermGenpesan ruang menunjukkan bahwa daerah Generation Tetap di memori habis.

Aplikasi Java apa pun diizinkan untuk menggunakan memori dalam jumlah terbatas. Jumlah persis memori aplikasi tertentu Anda dapat menggunakan ditentukan selama startup aplikasi.

Memori Java dipisahkan menjadi beberapa wilayah yang dapat dilihat pada gambar berikut:

masukkan deskripsi gambar di sini

Metaspace: Ruang memori baru lahir

JDK 8 HotSpot JVM sekarang menggunakan memori asli untuk representasi metadata kelas dan disebut Metaspace; mirip dengan Oracle JRockit dan IBM JVM.

Berita baiknya adalah itu berarti tidak ada lagi java.lang.OutOfMemoryError: PermGenmasalah ruang dan tidak perlu lagi Anda menyetel dan memantau ruang memori ini lagi menggunakan Java_8_Download atau lebih tinggi.

Santosh Jadi
sumber
17

1) Meningkatkan Ukuran Memori PermGen

Hal pertama yang bisa dilakukan adalah membuat ukuran ruang tumpukan generasi permanen lebih besar. Ini tidak dapat dilakukan dengan argumen JVM –Xms (atur ukuran heap awal) dan –Xmx (atur ukuran heap maksimum), karena seperti yang disebutkan, ruang heap generasi permanen sepenuhnya terpisah dari ruang Java Heap biasa, dan argumen ini di atur ruang untuk ruang heap Java biasa ini. Namun, ada argumen serupa yang dapat digunakan (setidaknya dengan jvms Sun / OpenJDK) untuk membuat ukuran generasi permanen lebih besar:

 -XX:MaxPermSize=128m

Default adalah 64m.

2) Aktifkan Sweeping

Cara lain untuk mengatasinya adalah dengan membiarkan kelas diturunkan sehingga PermGen Anda tidak pernah habis:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Hal-hal seperti itu berhasil bagiku di masa lalu. Namun satu hal, ada trade off kinerja yang signifikan dalam menggunakannya, karena sapuan permgen akan membuat seperti 2 permintaan tambahan untuk setiap permintaan yang Anda buat atau sesuatu di sepanjang garis itu. Anda harus menyeimbangkan penggunaan Anda dengan pengorbanan.

Anda dapat menemukan detail kesalahan ini.

http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html

faisalbhagat
sumber
Pos bagus @faisalbhagat faisalbhagat.blogspot.com/2014/09/…
leomeurer
Opsi 2 bagus, tetapi hanya diperingatkan bahwa itu tidak boleh digunakan di lingkungan produksi. Biasanya lebih baik menyimpannya di lingkungan pengembangan saja. Namun PermGen dihapus pada Java 8 openjdk.java.net/jeps/122
hdost
16

Atau, Anda dapat beralih ke JRockit yang menangani permgen berbeda dari jvm sun. Biasanya memiliki kinerja yang lebih baik.

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

Jeremy
sumber
4
Meskipun JRockit memang tidak memiliki PermGen, tetapi ini tidak akan membantu dalam jangka panjang. Anda akan mendapatkan java.lang.OutOfMemoryError: There is insufficient native memorysebagai gantinya.
stracktracer
14

Saya punya masalah yang kita bicarakan di sini, skenario saya adalah eclipse-helios + tomcat + jsf dan apa yang Anda lakukan adalah membuat penerapan aplikasi sederhana untuk tomcat. Saya menunjukkan masalah yang sama di sini, menyelesaikannya sebagai berikut.

Dalam gerhana pergi ke tab server klik dua kali pada server terdaftar dalam kasus saya kucing jagoan 7.0, itu membuka file server saya informasi pendaftaran umum. Pada bagian "Informasi Umum" klik pada tautan "Buka konfigurasi peluncuran" , ini membuka pelaksanaan opsi server di tab Argumen di argumen VM ditambahkan di akhir dua entri ini

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

dan siap.

Hugo Mendoza
sumber
14

Jawaban paling sederhana hari ini adalah menggunakan Java 8.

Ini tidak lagi menyimpan memori khusus untuk ruang PermGen, memungkinkan memori PermGen untuk bergabung dengan kumpulan memori biasa.

Perlu diingat bahwa Anda harus menghapus semua -XXPermGen...=...parameter startup JVM non-standar jika Anda tidak ingin Java 8 mengeluh bahwa mereka tidak melakukan apa-apa.

Edwin Buck
sumber
Halo, jawaban ini sudah diberikan: stackoverflow.com/a/22897121/505893 . Harap hapus jawaban Anda, untuk kejelasan. Jika perlu Anda dapat meningkatkan jawaban yang saya sebutkan. Terima kasih;)
kebiruan
6
@Bluish Terima kasih telah menunjukkan itu; Namun, jawaban itu berjalan menyamping saat berbicara tentang OutOfMemoryExceptions dan membocorkan metadata. Itu juga gagal menyebutkan poin yang sangat penting dari menghapus opsi PermGen. Singkatnya, saya tidak yakin saya akan memperbaiki jawabannya, melainkan menulis ulang. Jika itu hanya touch-up cepat, saya akan merasa kurang ragu-ragu, tetapi sepertinya itu akan lebih dari touch-up cepat, dan saya benci untuk menyinggung penulis aslinya. Tetap saja, daftar jawaban ini adalah makan malam anjing yang berantakan, dan mungkin membunuh posting saya adalah yang terbaik.
Edwin Buck
8
  1. Buka tomcat7w dari direktori bin Tomcat atau ketik Monitor Tomcat di menu mulai (jendela tab dibuka dengan berbagai informasi layanan).
  2. Di area teks Opsi Java tambahkan baris ini:

    -XX:MaxPermSize=128m
  3. Setel Memori Awal ke 1024 (opsional).
  4. Atur Maximum Memory Pool ke 1024 (opsional).
  5. Klik Oke.
  6. Mulai ulang layanan Tomcat.
Lucky
sumber
6

Perm gen space error terjadi karena penggunaan ruang besar daripada jvm menyediakan ruang untuk mengeksekusi kode.

Solusi terbaik untuk masalah ini dalam sistem operasi UNIX adalah mengubah beberapa konfigurasi pada file bash. Langkah-langkah berikut menyelesaikan masalah.

Jalankan perintah gedit .bashrcpada terminal.

Buat JAVA_OTPSvariabel dengan nilai berikut:

export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"

Simpan file bash. Jalankan perintah exec bash di terminal. Mulai ulang server.

Saya harap pendekatan ini akan mengatasi masalah Anda. Jika Anda menggunakan versi Java lebih rendah dari 8 masalah ini kadang-kadang terjadi. Tetapi jika Anda menggunakan Java 8 masalah tidak pernah terjadi.

Darshan
sumber
5

Meningkatkan ukuran Generasi Permanen atau mengubah parameter GC TIDAK akan membantu jika Anda memiliki kebocoran memori nyata. Jika aplikasi Anda atau pustaka pihak ketiga yang digunakannya, kebocoran kelas loader satu-satunya solusi nyata dan permanen adalah menemukan kebocoran ini dan memperbaikinya. Ada sejumlah alat yang dapat membantu Anda, salah satunya adalah Plumbr , yang baru saja merilis versi baru dengan kemampuan yang diperlukan.

Nikem
sumber
5

Juga jika Anda menggunakan log4j di aplikasi web Anda, periksa paragraf ini di dokumentasi log4j .

Tampaknya jika Anda menggunakan PropertyConfigurator.configureAndWatch("log4j.properties"), Anda menyebabkan kebocoran memori saat Anda menganggur dari aplikasi web Anda.

sermojohn
sumber
4

Saya memiliki kombinasi Hibernate + Eclipse RCP, mencoba menggunakan -XX:MaxPermSize=512mdan -XX:PermSize=512mdan sepertinya berfungsi untuk saya.

Pankaj Shinde
sumber
4

Setel -XX:PermSize=64m -XX:MaxPermSize=128m. Kemudian Anda juga dapat mencoba meningkatkan MaxPermSize. Semoga ini akan berhasil. Hal yang sama berlaku untuk saya. Pengaturan hanya MaxPermSizetidak berhasil untuk saya.

sandeep
sumber
4

Saya mencoba beberapa jawaban dan satu-satunya yang akhirnya berhasil adalah konfigurasi untuk plugin kompiler di pom:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
        <source>1.6</source>
        <target>1.6</target>
        <!-- prevent PermGen space out of memory exception -->
        <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
    </configuration>
</plugin>

semoga yang ini membantu.

kiwilisk
sumber
"argLine" tidak dikenali oleh maven-compiler-plugin 2.4. ini hanya mendukung "compilerArgument", yang memberikan kesalahan: <compilerArgument> -XX: MaxPermSize = 256m </compilerArgument> [KESALAHAN] Gagal mengeksekusi javac, tetapi tidak dapat menguraikan kesalahan: javac: flag tidak valid: -XX: MaxPermSize = 256m Penggunaan : javac <options> <source files>
Alex
Jika fase kompilasi Anda kehabisan permgen, atur <compilerArgument> pada maven-compiler-plugin. Jika tes unit kehen dari permgen, atur <argLine> di maven-surefire-plugin
qwerty
4

menyelesaikan ini untukku juga; Namun, saya perhatikan bahwa waktu restart servlet jauh lebih buruk, jadi sementara itu lebih baik dalam produksi, itu semacam hambatan dalam pengembangan.

Tim Howland
sumber
3

Konfigurasi memori tergantung pada sifat aplikasi Anda.

Apa yang sedang kamu lakukan?

Berapa jumlah transaksi yang harus dilakukan?

Berapa banyak data yang Anda muat?

dll.

dll.

dll

Mungkin Anda dapat membuat profil aplikasi Anda dan mulai membersihkan beberapa modul dari aplikasi Anda.

Rupanya ini dapat terjadi setelah memindahkan aplikasi beberapa kali

Tomcat memiliki penyebaran panas tetapi menghabiskan memori. Coba mulai ulang wadah Anda sesekali. Anda juga perlu mengetahui jumlah memori yang diperlukan untuk berjalan dalam mode produksi, ini sepertinya waktu yang tepat untuk penelitian itu.

OscarRyz
sumber
3

Mereka mengatakan bahwa rev terbaru dari Tomcat (6.0.28 atau 6.0.29) menangani tugas pemindahan servlet jauh lebih baik.

Tony Ennis
sumber
3

Saya mengalami masalah yang persis sama, tetapi sayangnya tidak ada solusi yang disarankan yang bekerja untuk saya. Masalahnya tidak terjadi selama penyebaran, dan saya tidak melakukan penyebaran panas.

Dalam kasus saya, masalah terjadi setiap kali pada titik yang sama selama eksekusi aplikasi web saya, saat menghubungkan (via hibernate) ke database.

Tautan ini (juga disebutkan sebelumnya) memang menyediakan bagian dalam yang cukup untuk menyelesaikan masalah. Memindahkan driver jdbc- (mysql) dari WEB-INF dan masuk ke folder jre / lib / ext / tampaknya telah menyelesaikan masalah. Ini bukan solusi yang ideal, karena meningkatkan ke JRE yang lebih baru akan mengharuskan Anda untuk menginstal ulang driver. Kandidat lain yang dapat menyebabkan masalah serupa adalah log4j, jadi Anda mungkin ingin memindahkannya juga

Maze
sumber
Jika Anda tidak ingin menyertakan driver di jre / lib / ext, Anda mungkin bisa mendapatkan hasil yang sama dengan memasukkan driver di classpath startup container Anda. java -cp /path/to/jdbc-mysql-driver.jar:/path/to/container/bootstrap.jar container.Start
Scot
3

Langkah pertama dalam kasus tersebut adalah memeriksa apakah GC diizinkan untuk menurunkan kelas dari PermGen. Standar JVM agak konservatif dalam hal ini - kelas dilahirkan untuk hidup selamanya. Jadi, sekali dimuat, kelas tetap berada dalam memori bahkan jika tidak ada kode yang menggunakannya lagi. Ini bisa menjadi masalah ketika aplikasi membuat banyak kelas secara dinamis dan kelas yang dihasilkan tidak diperlukan untuk periode yang lebih lama. Dalam kasus seperti itu, memungkinkan JVM untuk menurunkan definisi kelas dapat membantu. Ini dapat dicapai dengan menambahkan hanya satu parameter konfigurasi ke skrip startup Anda:

-XX:+CMSClassUnloadingEnabled

Secara default ini disetel ke false dan untuk mengaktifkannya, Anda perlu secara eksplisit mengatur opsi berikut dalam opsi Java. Jika Anda mengaktifkan CMSClassUnloadingEnabled, GC juga akan menyapu PermGen dan menghapus kelas yang tidak lagi digunakan. Perlu diingat bahwa opsi ini hanya akan berfungsi ketika UseConcMarkSweepGC juga diaktifkan menggunakan opsi di bawah ini. Jadi ketika menjalankan ParallelGC atau, Tuhan melarang, Serial GC, pastikan Anda telah mengatur GC Anda ke CMS dengan menentukan:

-XX:+UseConcMarkSweepGC
sendon1982
sumber
3

Menugaskan Tomcat lebih banyak memori BUKAN solusi yang tepat.

Solusi yang benar adalah dengan melakukan pembersihan setelah konteksnya dihancurkan dan diciptakan kembali (penyebaran panas). Solusinya adalah menghentikan kebocoran memori.

Jika Tomcat / Webapp Server memberi tahu Anda bahwa gagal untuk membatalkan registrasi driver (JDBC), maka batalkan registrasi. Ini akan menghentikan kebocoran memori.

Anda dapat membuat ServletContextListener dan mengkonfigurasinya di web.xml Anda. Berikut ini adalah contoh ServletContextListener:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

/**
 * 
 * @author alejandro.tkachuk / calculistik.com
 *
 */
public class AppContextListener implements ServletContextListener {

    private static final Logger logger = Logger.getLogger(AppContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        logger.info("AppContextListener started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        logger.info("AppContextListener destroyed");

        // manually unregister the JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("Unregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error unregistering driver %s", driver), e);
            }

        }

        // manually shutdown clean up threads
        try {
            AbandonedConnectionCleanupThread.shutdown();
            logger.info("Shutting down AbandonedConnectionCleanupThread");
        } catch (InterruptedException e) {
            logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
            e.printStackTrace();
        }        
    }
}

Dan di sini Anda mengkonfigurasinya di web.xml Anda:

<listener>
    <listener-class>
        com.calculistik.mediweb.context.AppContextListener 
    </listener-class>
</listener>  
Alejandro Pablo Tkachuk
sumber
2

"Mereka" salah karena saya menjalankan 6.0.29 dan memiliki masalah yang sama bahkan setelah mengatur semua opsi. Seperti yang dikatakan Tim Howland di atas, opsi-opsi ini hanya menunda yang tak terhindarkan. Mereka memungkinkan saya untuk memindahkan 3 kali sebelum memukul kesalahan daripada setiap kali saya memindahkan.

Ross Peoples
sumber
2

Jika Anda mendapatkan ini di IDE gerhana, bahkan setelah mengatur parameter --launcher.XXMaxPermSize,, -XX:MaxPermSizedll, masih jika Anda mendapatkan kesalahan yang sama, kemungkinan besar adalah bahwa gerhana menggunakan versi kereta JRE yang akan diinstal oleh beberapa aplikasi pihak ketiga dan diatur ke default. Versi kereta ini tidak mengambil parameter PermSize dan jadi apa pun yang Anda atur, Anda masih terus mendapatkan kesalahan memori ini. Jadi, di eclipse.ini Anda tambahkan parameter berikut:

-vm <path to the right JRE directory>/<name of javaw executable>

Pastikan juga Anda mengatur JRE default di preferensi di gerhana ke versi java yang benar.

Hrishikesh Kumar
sumber
2

Satu-satunya cara yang berhasil bagi saya adalah dengan JVM JRockit. Saya memiliki MyEclipse 8.6.

Tumpukan JVM menyimpan semua objek yang dihasilkan oleh program Java yang sedang berjalan. Java menggunakan newoperator untuk membuat objek, dan memori untuk objek baru dialokasikan pada heap saat dijalankan. Pengumpulan sampah adalah mekanisme untuk secara otomatis membebaskan memori yang terkandung oleh objek yang tidak lagi dirujuk oleh program.

pengguna1985910
sumber
2

Saya mengalami masalah serupa. Tambang saya adalah JDK 7 + Maven 3.0.2 + Struts 2.0 + proyek berbasis ketergantungan ketergantungan GUICE Google.

Setiap kali saya mencoba menjalankan mvn clean packageperintah, itu menunjukkan kesalahan berikut dan "BUILD FAILURE" terjadi

org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; pengecualian bersarang adalah java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException Disebabkan oleh: java.lang.OutOfMemoryError: Ruang PermGen

Saya mencoba semua tips dan trik yang bermanfaat di atas tetapi sayangnya tidak ada yang berhasil untuk saya. Apa yang berhasil bagi saya dijelaskan langkah demi langkah di bawah ini: =>

  1. Buka pom.xml Anda
  2. Pencarian untuk <artifactId>maven-surefire-plugin</artifactId>
  3. Tambahkan <configuration>elemen baru dan kemudian <argLine>sub elemen yang lulus -Xmx512m -XX:MaxPermSize=256mseperti yang ditunjukkan di bawah ini =>

<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

Semoga bisa membantu, selamat pemrograman :)

NIKHIL CHAURASIA
sumber