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?


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 .


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.


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 .


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.


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).


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


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


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();

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.


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



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


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.


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.


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.

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.


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.


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.


4

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


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.


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.


"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.


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.


3

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


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


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

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>  

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.


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.


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.


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 :)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.