Apa yang perlu Anda ketahui terlebih dahulu
1. Pemrogram C/C++ mengelola memorinya sendiri, sementara memori Java secara otomatis diambil kembali oleh GC.
Meskipun saya tidak terlalu paham dengan C++, saya mungkin tidak membuat kesalahan yang masuk akal dalam hal ini.
2. Apa itu kebocoran memori?
Kebocoran memori mengacu pada keberadaan memori dalam sistem yang tidak dapat didaur ulang, terkadang menyebabkan kekurangan memori atau sistem crash.
Di C/C++, kebocoran memori terjadi ketika memori yang dialokasikan tidak dilepaskan.
3. Ada kebocoran memori di Java. Kita harus mengakuinya terlebih dahulu sebelum kita melanjutkan pembahasannya. Meskipun Java mengalami kebocoran memori, pada dasarnya Anda tidak perlu mempedulikannya, terutama bagi mereka yang tidak terlalu paham dengan kode itu sendiri.
Kebocoran memori di Java tentu berarti: ada benda-benda tidak berguna yang tidak dapat didaur ulang oleh pengumpul sampah.
Dan meskipun ada masalah kebocoran memori, masalah tersebut mungkin tidak muncul.
4. Parameter di Java semuanya diteruskan berdasarkan nilai.
Pada dasarnya tidak ada keberatan terhadap tipe dasar, tapi kita tidak bisa menolak tipe referensi.
Kebocoran memori Java
1. Memori tumpukan meluap (outOfMemoryError: java heap space)
Dalam spesifikasi JVM, memori di heap digunakan untuk menghasilkan instance objek dan array.
Jika dibagi lagi, heap memory juga dapat dibagi menjadi generasi muda dan generasi tua yang mencakup satu area eden dan dua area survivor.
Ketika objek baru dibuat, proses aplikasi memori adalah sebagai berikut:
a.JVM pertama-tama mencoba mengalokasikan memori yang diperlukan untuk objek baru di area eden;
b. Jika ukuran memori mencukupi maka aplikasi dihentikan, jika tidak maka langkah selanjutnya adalah;
c. JVM memulai youngGC dan mencoba melepaskan objek-objek yang tidak aktif di kawasan Eden. Setelah dilepaskan, jika ruang Eden masih belum cukup untuk menempatkan objek-objek baru, maka JVM mencoba memasukkan beberapa objek aktif di Eden ke dalam area Survivor;
d.Area Survivor digunakan sebagai area pertukaran perantara antara Eden dan Old. Apabila area OLD mempunyai ruang yang cukup, maka benda-benda yang ada di area Survivor akan dipindahkan ke area Old, jika tidak maka akan dipertahankan di area Survivor;
e.Ketika tidak ada cukup ruang di area OLD, JVM akan melakukan GC penuh di area OLD;
f. Setelah GC penuh, jika area Survivor dan OLD masih tidak dapat menyimpan beberapa objek yang disalin dari Eden, menyebabkan JVM tidak dapat membuat area memori untuk objek baru di area Eden, akan muncul "kesalahan memori habis":
outOfMemoryError:ruang tumpukan java
2. Memori meluap di area metode (outOfMemoryError: permgem space)
Dalam spesifikasi JVM, area metode terutama menyimpan informasi kelas, konstanta, variabel statis, dll.
Oleh karena itu, jika program memuat terlalu banyak kelas, atau menggunakan teknologi pembuatan proxy dinamis seperti refleksi atau gclib, hal ini dapat menyebabkan kelebihan memori di area ini. Umumnya, pesan kesalahan saat terjadi kelebihan memori di area ini adalah:
outOfMemoryError:ruang permgem
3. Tumpukan tumpukan benang (java.lang.StackOverflowError)
Tumpukan thread adalah struktur memori yang unik untuk thread, jadi masalah dengan tumpukan thread pasti merupakan kesalahan yang dihasilkan saat thread sedang berjalan.
Umumnya, thread stack overflow disebabkan oleh rekursi yang terlalu dalam atau terlalu banyak level pemanggilan metode.
Pesan kesalahan saat terjadi stack overflow adalah:
Jawa. bahasa. StackOverflowError
Beberapa skenario kebocoran memori:
1. Benda yang berumur panjang mempunyai referensi terhadap benda yang berumur pendek.
Ini adalah skenario kebocoran memori yang paling umum dan masalah umum dalam desain kode.
Misalnya: jika variabel lokal di-cache di peta statis global dan tidak ada operasi pembersihan, peta akan menjadi semakin besar seiring berjalannya waktu, sehingga menyebabkan kebocoran memori.
2. Ubah nilai parameter objek di hashset, dan parameternya adalah bidang yang digunakan untuk menghitung nilai hash.
Setelah suatu objek disimpan dalam koleksi HashSet, bidang dalam objek yang berpartisipasi dalam penghitungan nilai hash tidak dapat diubah, jika tidak, nilai hash objek yang dimodifikasi akan berbeda dari nilai hash ketika awalnya disimpan dalam koleksi HashSet , dalam hal ini, meskipun metode berisi menggunakan referensi objek saat ini sebagai parameter untuk mengambil objek dari koleksi HashSet, metode tersebut akan mengembalikan hasil bahwa objek tidak dapat ditemukan, yang juga akan mengakibatkan kegagalan untuk menemukan. menghapus objek saat ini dari koleksi HashSet, menyebabkan kebocoran Memori.
3. Atur jumlah koneksi dan waktu mematikan mesin
Membuka koneksi yang sangat intensif sumber daya dalam waktu lama juga dapat menyebabkan kebocoran memori.
Mari kita lihat contoh kebocoran memori:
public class Stack { Objek pribadi[] elemen=Objek baru[10]; ukuran int pribadi = 0; public void push(Objek e){ sureCapacity(); ukuran == 0) lempar baruEmptyStackException(); kembalikan elemen[--ukuran]; } private void sureCapacity(){ if(elements.length == ukuran){ Objek[] oldElements = elemen; elemen = Objek baru[2 * elemen. panjang+1]; Sistem. arraycopy(oldElements,0, elemen, 0, ukuran);
Prinsip di atas seharusnya sangat sederhana. Jika 10 elemen ditambahkan ke tumpukan dan kemudian semuanya dikeluarkan, meskipun tumpukan tersebut kosong dan tidak ada yang kita inginkan, objek ini tidak dapat didaur ulang. Kondisi: Tidak berguna, tidak dapat didaur ulang.
Namun keberadaan hal seperti itu belum tentu menimbulkan konsekuensi apa pun jika tumpukan ini digunakan lebih sedikit,
Cuma buang-buang memori beberapa K saja. Lagi pula, memori kita sudah sampai G, jadi apa dampaknya? Lagi pula, benda ini akan segera didaur ulang, jadi apa bedanya? Mari kita lihat dua contoh di bawah ini.
Contoh 1
kelas publik Buruk{ public static Stack s=Stack(); statis{ s. push(Objek baru()); s. pop(); //Ada kebocoran memori pada suatu objek di sini. push(new Object()); //Objek di atas dapat didaur ulang, yang setara dengan penyembuhan diri}}
Karena bersifat statis, ia akan tetap ada hingga program keluar, tetapi kita juga dapat melihat bahwa ia memiliki fungsi penyembuhan diri.
Artinya, jika Stack Anda memiliki paling banyak 100 objek, maka paling banyak hanya 100 objek yang tidak dapat didaur ulang. Faktanya, ini seharusnya mudah dipahami. Stack menyimpan 100 referensi secara internal , karena begitu kami membuat kemajuan baru, referensi sebelumnya akan hilang dengan sendirinya!
Contoh 2
kelas publik NotTooBad{ public void doSomething(){ Stack s=tumpukan baru(); push(Objek baru()); //kode lain. pop();//Ini juga mengakibatkan objek tidak dapat didaur ulang dan memori bocor. }//Keluar dari metode, s secara otomatis tidak valid, s dapat didaur ulang, dan referensi di dalam Stack secara alami hilang, jadi //Penyembuhan diri juga dapat dilakukan di sini, dan dapat dikatakan bahwa metode ini tidak memiliki masalah kebocoran memori, tapi nanti akan diserahkan // Hanya diberikan kepada GC, karena tertutup dan tidak terbuka untuk dunia luar Kode 99. 9999% // situasi tidak akan berdampak apa pun. Tentu saja, jika Anda menulis kode seperti itu, tidak akan berdampak buruk, tetapi // pasti dapat dikatakan sebagai kode sampah! Saya akan menambahkan satu di dalamnya. Perulangan for yang kosong tidak akan berdampak besar, bukan?
Dua contoh di atas hanyalah hal sepele, namun kebocoran memori di C/C++ tidaklah Buruk, melainkan Terburuk.
Jika tidak didaur ulang di satu tempat, tidak akan pernah bisa didaur ulang. Jika Anda sering memanggil metode ini, memori akan habis!
Karena Java juga memiliki fungsi penyembuhan diri (saya sendiri yang menamakannya dan belum mengajukan paten), masalah kebocoran memori Java hampir dapat diabaikan, tetapi mereka yang mengetahuinya sebaiknya tidak melakukannya.
Untuk menghindari kebocoran memori, Anda dapat merujuk pada saran berikut saat menulis kode:
1. Lepaskan referensi ke objek yang tidak berguna sedini mungkin;
2. Gunakan pemrosesan string, hindari penggunaan String, dan gunakan StringBuffer secara ekstensif. Setiap objek String harus menempati area memori yang independen;
3. Gunakan variabel statis sesedikit mungkin, karena variabel statis disimpan dalam pembangkitan permanen (area metode), dan pembangkitan permanen pada dasarnya tidak ikut serta dalam pengumpulan sampah;
4. Hindari membuat objek secara berulang;
5. Membuka file besar atau mengambil terlalu banyak data dari database sekaligus dapat dengan mudah menyebabkan memori meluap, jadi di tempat-tempat ini, Anda harus menghitung secara kasar jumlah data maksimum, dan menetapkan nilai ruang memori minimum dan maksimum yang diperlukan.