Spesifikasi mesin virtual Java menetapkan bahwa memori JVM dibagi menjadi beberapa blok, seperti tumpukan, tumpukan, penghitung program, area metode, dll. Dalam implementasi JVM hotspot, memori tumpukan dibagi menjadi tiga bagian, generasi baru, usia tua, dan pita persisten. Pita persisten mengimplementasikan area metode yang ditentukan dalam spesifikasi, dan berbagai bagian model memori akan memiliki kesalahan outofmemoryError yang sesuai. Selanjutnya, mari kita bahas secara terpisah. Saya percaya sebagian besar pengembang mengalami kesalahan ini, dan alasan kesalahan ini sebagian besar disebabkan oleh alasan berikut:
Memori JVM terlalu kecil dan programnya tidak ketat, menghasilkan terlalu banyak sampah.
Ada beberapa penyebab umum pengecualian outofmemoryerror:
Permintaan kesalahan umum untuk kesalahan ini:
Stackoverflowerror
Stack Overflow melempar kesalahan java.lang.stackoverflowerror. Ini terjadi karena kedalaman tumpukan melebihi kedalaman maksimum yang diizinkan oleh mesin virtual saat metode berjalan. Situasi ini biasanya terjadi karena kesalahan program. Misalnya, menulis rekursi mati dapat menyebabkan situasi ini. Mari kita simulasikan overflow memori dalam situasi ini melalui sepotong kode.
impor java.util.*; impor java.lang.*; kelas publik oomtest {public void stackoverflowmethod () {stackoverflowmethod (); } public static void main (string ... args) {oomtest oom = oomtest baru (); oom.stackoverflowmethod (); }} Menjalankan kode di atas akan melempar pengecualian berikut:
Pengecualian di Thread "Main" java.lang.Stackoverflowerror di oomtest.stackoverflowmethod (oomtest.java:6)
Heap Overflow (OutofMemoryError: Java Heap Space)
Ketika memori heap meluap, mesin virtual melempar java.lang.outofmemoryError: Java Heap Space. Ketika ini terjadi, kita perlu menganalisisnya secara khusus berdasarkan file dump yang dihasilkan ketika memori meluap (-xx: +heapdumponoutOfmemoryErrorjvm parameter startup perlu ditambahkan). Ketika masalah seperti itu terjadi, itu mungkin kebocoran memori atau overflow memori.
Jika memori bocor, kita perlu mencari tahu bagaimana objek bocor dirujuk oleh root GC, dan kemudian menganalisis penyebab kebocoran melalui rantai referensi.
Jika ada masalah meluap memori, itu sering karena program membutuhkan lebih banyak memori daripada memori yang kami konfigurasi untuk mesin virtual. Dalam hal ini, kita dapat menggunakan -xmx untuk menyelesaikan masalah ini.
Di bawah ini kami menunjukkan luapan situasi ini melalui kode berikut:
impor java.util.*; impor java.lang.*; kelas publik oomtest {public static void main (string ... args) {list <byte []> buffer = arraylist baru <byte []> (); buffer.add (byte baru [10*1024*1024]); }} Kami menjalankan kode di atas melalui perintah berikut:
Java -Verbose: gc -xmn10m -xms20m -xmx20m -xx:+printgc oomtest
Program ini memasukkan informasi berikut:
[GC 1180K-> 366K (19456K), 0,0037311 detik] [GC penuh 366k-> 330k (19456K), 0,0098740 SECS] [GC 330K-> 292K (19456K), 0,0090244 Exception dalam Buas "JAV.RAF.RAV.RAV.RAF. di oomtest.main (oomtest.java:7)
Dari hasil berjalan, kita dapat melihat bahwa JVM melakukan Minor GC sekali dan dua kali GC utama. Dari output utama GC, dapat dilihat bahwa laju penggunaan area lama setelah GC adalah 134k, dan array byte adalah 10m, yang menambahkan lebih besar dari ruang generasi lama, sehingga pengecualian dilemparkan. Jika -xms21m dan -xmx21m disesuaikan, maka operasi GC tidak akan dipicu dan tidak akan ada pengecualian.
Melalui percobaan di atas, kesimpulan telah diverifikasi dari samping: ketika objek lebih besar dari memori yang tersisa dari generasi baru, itu akan ditempatkan langsung ke usia tua. Ketika kenangan yang tersisa dari usia tua masih tidak dapat diletakkan, pengumpulan sampah akan dipicu. Jika masih tidak dapat diletakkan setelah koleksi, pengecualian memori overflow akan dilemparkan.
Ruang Permgen
Kita tahu bahwa Hotspot JVM mengimplementasikan area metode dalam spesifikasi mesin virtual Java melalui pita persisten, dan runtime constant pool disimpan di area metode. Oleh karena itu, overflow pita persisten dapat berupa runtime constant overflow, atau objek kelas yang disimpan di area metode tidak didaur ulang dalam waktu atau memori yang ditempati oleh informasi kelas melebihi konfigurasi kami. Ketika pita kegigihan meluap, java.lang.outofmemoryError: Ruang Permgen dilemparkan.
Saya mungkin mengalami masalah ini dalam skenario berikut saat bekerja.
Saat menggunakan penyebaran panas dari beberapa server aplikasi, kami akan menemukan penyebaran panas beberapa kali dan menemukan memori itu meluap. Ini karena setelah setiap penyebaran panas, kelas asli belum dihapus.
Jika aplikasi itu sendiri lebih besar dan melibatkan lebih banyak pustaka kelas, masalah ini juga dapat terjadi ketika memori yang kami alokasikan ke pita persisten (ditetapkan oleh -xx: permsize dan -xx: maxpermsize) relatif kecil.
Beberapa kerangka kerja pihak ketiga, seperti Spring dan Hibernate, semuanya menerapkan beberapa fungsi yang ditingkatkan melalui teknologi generasi bytecode (seperti CGLIB), yang mungkin memerlukan area metode yang lebih besar untuk menyimpan file kelas yang dihasilkan secara dinamis.
Kita tahu bahwa konstanta tali di Java ditempatkan di kolam konstan. Ketika metode string.intern () dijalankan, ia akan memeriksa apakah objek yang sama dengan string ini disimpan di kumpulan konstan. Jika ada, langsung kembalikan referensi ke objek di kumpulan konstan. Jika tidak ada, tambahkan string ini ke kumpulan konstan terlebih dahulu, dan kemudian kembalikan referensi ke string. Kemudian kita dapat mensimulasikan overflow area konstan selama runtime melalui metode string. Mari kita simulasikan situasi ini melalui kode berikut:
impor java.util.*; impor java.lang.*; kelas publik oomtest {public static void main (string ... args) {list <string> list = new ArrayList <string> (); while (true) {list.add (uuid.randomuuid (). tostring (). magang ()); }}}Kami menjalankan kode di atas melalui perintah berikut:
Java -Verbose: gc -xmn5m -xms10m -xmx10m -xx: maxpermsize = 1m -xx:+printgc oomtest
Input setelah berjalan ditunjukkan pada gambar di bawah ini:
Pengecualian di Thread "Main" java.lang.outofmemoryError: Ruang Permgen di java.lang.string.intern (metode asli) di oomtest.main (oomtest.java:8)
Melalui kode di atas, kami berhasil mensimulasikan overflow pool konstan selama runtime. Dari ruang Permgen dalam output, kita dapat melihat bahwa pita persisten memang meluap, yang juga memverifikasi pernyataan bahwa hotspot JVM mengimplementasikan area metode melalui pita persisten seperti yang disebutkan sebelumnya.
OutofmemoryError: Tidak dapat membuat utas asli
Akhirnya, mari kita lihat kesalahan java.lang.outofmemoryError: Tidak dapat membuat utas natvie. Ketika ini terjadi, biasanya disebabkan oleh dua situasi berikut:
Jumlah utas yang dibuat oleh program melebihi batas sistem operasi. Untuk sistem Linux, kita dapat melihat batasan ini melalui Ulimit -u.
Memori yang dialokasikan ke mesin virtual terlalu besar, sehingga terlalu sedikit memori asli saat membuat utas. Kita semua tahu bahwa sistem operasi memiliki batas pada memori setiap proses. Saat memulai JVM, itu setara dengan memulai proses. Jika salah satu proses kami menempati memori 4G, maka memori yang tersisa dihitung melalui rumus berikut adalah memori yang dapat digunakan saat membangun tumpukan benang. Total memori yang tersedia untuk stack utas = 4G- (nilai -xmx)-(-xx: nilai maxpermsize)-memori yang ditempati oleh penghitung program ditunjukkan oleh rumus di atas bahwa semakin besar nilai -xmx dan maxpermSize, semakin kecil ruang yang tersedia untuk tumpukan utas. Ketika kapasitas tumpukan yang dikonfigurasi oleh parameter -XSS tetap tidak berubah, semakin kecil jumlah utas yang dapat dibuat. Oleh karena itu, jika tidak mungkin untuk membuat utas asli karena situasi ini, maka kami meningkatkan total memori yang ditempati oleh proses, atau mengurangi -xmx atau -xss untuk mencapai tujuan membuat lebih banyak utas.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.