Di Java, manajemen memorinya mencakup dua aspek: alokasi memori (saat membuat objek Java) dan daur ulang memori. Kedua aspek pekerjaan secara otomatis diselesaikan oleh JVM, mengurangi kesulitan belajar untuk pemrogram Java dan menghindari bahaya memori yang beroperasi secara langsung seperti C/C ++. Namun, justru karena manajemen memori sepenuhnya ditangani oleh JVM bahwa banyak pemrogram Java tidak lagi peduli dengan alokasi memori, mengakibatkan banyak program yang tidak efisien dan mengonsumsi memori. Oleh karena itu, pemrogram Java harus memahami JVM pada akhirnya untuk menulis program yang lebih efisien dan memanfaatkan sepenuhnya memori terbatas.
1. Keadaan Java dalam Memori
Pertama, mari kita tulis kode sebagai contoh:
Orang.java
tes paket; import java.io.serializable; orang kelas publik mengimplementasikan serializable {static final long serialversionuid = 1l; Nama string; // Sebutkan teman orang; // teman publik () {} orang publik (nama string) {super (); this.name = name; }} Test.java
tes paket; tes kelas publik {public static void main (string [] args) {person p1 = orang baru ("kevin"); Orang p2 = orang baru ("hujan"); Orang p3 = orang baru ("cerah"); p1.friend = p2; p3 = p2; p2 = null; }} Jika Anda menggambar referensi objek dalam aspek utama dalam test.java di atas menjadi diagram referensi objek yang dimulai dari metode utama, seperti ini (simpul adalah objek dan referensi, dan tepi terarah adalah hubungan referensi):
Ketika program berjalan, setelah dianggap sebagai grafik terarah, itu dapat dibagi menjadi tiga jenis:
1) Keadaan yang dapat dicapai: Setelah suatu objek dibuat, lebih dari satu variabel referensi mengacu padanya. Dalam grafik yang diarahkan, Anda dapat menavigasi ke objek dari titik awal, dan itu dalam keadaan yang dapat diakses.
2) Keadaan yang dapat dipulihkan: Jika suatu objek dalam program tidak lagi memiliki variabel referensi yang mengacu padanya, itu pertama -tama akan memasuki keadaan yang dapat dipulihkan, dan pada saat ini, ia tidak dapat menavigasi ke objek dari titik awal grafik yang diarahkan. Dalam keadaan ini, mekanisme pengumpulan sampah sistem siap mendaur ulang memori yang ditempati oleh objek. Sebelum daur ulang, sistem akan memanggil metode finalisasi () untuk membersihkan sumber daya. Jika lebih dari satu variabel referensi direklamasi setelah sumber daya diurutkan, objek akan menjadi keadaan yang dapat diakses lagi; Kalau tidak, ia akan memasuki keadaan yang tidak terjangkau.
3) Keadaan yang tidak dapat dijangkau: Ketika semua asosiasi objek terputus dan sistem memanggil metode finalisasi () untuk membersihkan sumber daya masih tidak membuat keadaan yang dapat dijangkau, maka objek akan kehilangan referensi secara permanen dan menjadi keadaan yang tidak dapat dijangkau, dan sistem akan benar -benar mendaur ulang sumber daya yang ditempati oleh objek.
Diagram transisi dari tiga negara bagian di atas adalah sebagai berikut:
2. 4 Referensi ke Objek oleh Java
1) Referensi Kuat: Buat objek dan tetapkan objek ini langsung ke variabel, misalnya: orang orang = orang baru ("cerah"); Tidak peduli seberapa ketat sumber daya sistem, objek yang dirujuk kuat tidak akan pernah didaur ulang, bahkan jika itu tidak akan digunakan lagi di masa depan.
2) Referensi Lembut: Diimplementasikan melalui kelas Softreference, misalnya: Softreference <Fone> p = Softreference baru <Fone> (orang baru ("hujan"));, ketika ingatannya sangat ketat, Anda akan didaur ulang, dan tidak akan didaur ulang di lain waktu, jadi sebelum menggunakannya, Anda harus menentukan apakah itu tidak akan ditentukan.
3) Referensi Lemah: Diimplementasikan melalui Kelas WeakReference, misalnya: Lemah Referensi <Fone> P = Referensi Lemah Baru <Fone> (orang baru ("hujan")); Terlepas dari apakah memori itu cukup, sistem pasti akan didaur ulang selama pengumpulan sampah.
4) Kutipan Virtual: Ini tidak dapat digunakan sendiri, ini terutama digunakan untuk melacak keadaan objek yang dikumpulkan. Diimplementasikan melalui kelas phantomreference dan kelas referensi antrian referensi, misalnya:
tes paket; impor java.lang.ref.phantomreference; impor java.lang.ref.referencequeue; tes kelas publik {public static void main (string [] args) {// Buat orang objek orang = orang baru ("Sunny"); // Buat Referensi Referensi Referensi Referensi <Son> rq = ReferenceQueue baru <sone> (); // Buat referensi virtual, biarkan referensi virtual ini referensi ke objek orang Phantomreference <Fone> pr = New PhantomReference <Fon> (Person, RQ); // selesaikan variabel referensi dan objek orang referensi orang = null; // Coba keluarkan objek yang dirujuk oleh referensi virtual // Saya menemukan bahwa program tidak dapat mengakses objek yang dirujuk melalui referensi virtual, sehingga output di sini adalah null system.out.println (pr.get ()); // System Pengumpulan Sampah Paksa.gc (); System.runfinalisasi (); // Karena begitu objek dalam referensi virtual didaur ulang, referensi virtual akan memasukkan antrian referensi // jadi gunakan referensi yang pertama kali memasukkan antrian dalam antrian untuk membandingkan dengan PR, dan output true system.out.println (rq.poll () == PR); }}Hasil Menjalankan:
3. Mekanisme Pengumpulan Sampah Java
Faktanya, koleksi sampah Java terutama melakukan dua hal: 1) Daur Ulang Memori 2) Defragmentasi
3.1 Algoritma Pengumpulan Sampah
1) Daur ulang serial (hanya satu CPU) dan daur ulang paralel (beberapa CPU bermanfaat): Daur ulang serial berarti bahwa tidak peduli berapa banyak CPU yang dimiliki sistem, selalu hanya satu CPU untuk melakukan operasi pengumpulan sampah. Daur ulang paralel berarti memecah seluruh pekerjaan daur ulang menjadi beberapa bagian, masing -masing bagian bertanggung jawab oleh satu CPU, sehingga beberapa CPU dapat didaur ulang secara paralel. Daur ulang paralel sangat efisien dalam eksekusi, tetapi meningkatkan kompleksitas, dan ada juga beberapa efek samping, seperti peningkatan memori secara acak.
2) Eksekusi dan Aplikasi Bersamaan berhenti: Seperti namanya, metode pengumpulan sampahnya akan menyebabkan suspensi aplikasi saat melakukan pengumpulan sampah. Meskipun pengumpulan sampah dari eksekusi bersamaan tidak akan menyebabkan aplikasi dijeda, karena eksekusi bersamaan sampah perlu menyelesaikan konflik dengan aplikasi (aplikasi dapat memodifikasi objek selama proses pengumpulan sampah), sistem overhead eksekusi secara bersamaan dari pengumpulan sampah lebih tinggi daripada stop-the-world, dan membutuhkan lebih banyak ingatan ketika pelaksanaan.
3) kompres dan non-kompres dan salinan:
① Kolektor sampah yang mendukung kompresi (Mark-Compression = Mark-Clear + Compression) akan memindahkan semua objek yang dapat dijangkau bersama-sama, dan kemudian mendaur ulang semua memori yang ditempati sebelumnya, mengurangi fragmentasi memori.
② Kolektor sampah yang tidak terkompresi (Mark-Clear) perlu dilalui dua kali. Pertama kali Anda pertama -tama mengakses semua objek yang dapat dijangkau dan menandai mereka sebagai keadaan yang dapat dijangkau. Kali kedua Anda memfasilitasi seluruh area memori dan mendaur ulang objek yang tidak ditandai dengan keadaan yang dapat dijangkau. Metode daur ulang ini tidak dikompresi dan tidak memerlukan memori ekstra, tetapi akan menghasilkan fragmentasi jika membutuhkan dua traversal.
③ Salin pengumpul sampah: Bagilah memori heap menjadi dua ruang yang identik, akses masing -masing objek yang dapat dijangkau dari root (mirip dengan titik awal grafik terarah sebelumnya), salin semua objek yang dapat dijangkau dalam ruang A ke ruang B, dan kemudian mendaur ulang ruang A pada satu waktu. Untuk algoritma ini, karena Anda hanya perlu mengakses semua objek yang dapat dijangkau, menyalin semua objek yang dapat dijangkau, dan secara langsung mendaur ulang seluruh ruang, mengabaikan objek yang tidak dapat dijangkau sama sekali, biaya melintasi ruang itu kecil, tetapi membutuhkan biaya penyalinan yang sangat besar dan lebih banyak memori.
3.2 Daur Ulang Generasional dari Heap Memory
1) Dasar untuk Daur Ulang Generasi:
① Panjang waktu kelangsungan hidup objek: Sebagian besar objek didaur ulang selama periode muda ② Generasi yang berbeda mengadopsi berbagai strategi daur ulang sampah: baru (waktu bertahan hidup singkat) lama (waktu bertahan hidup lama) jarang memiliki referensi antar objek
2) Generasi memori heap:
① Generasi Muda:
Mekanisme Pemeriksaan Siklus: Karena jumlah objek kecil, replikasi dan daur ulang digunakan.
Ⅱ Area konsolidasi: terdiri dari 1 area eden dan 2 area selamat. Dua area yang selamat pada saat yang sama, satu digunakan untuk menyimpan objek dan yang lainnya kosong; Setiap kali pengumpulan sampah generasi muda dilakukan, benda-benda yang dapat diakses di Eden dan dari disalin ke area ke, dan beberapa yang berumur panjang disalin ke usia tua, kemudian eden dan dari luar angkasa dibersihkan, dan akhirnya yang asli ke luar angkasa menjadi dari ruang angkasa, dan yang asli dari ruang menjadi ruang angkasa.
Ⅲ Sumber Objek: Sebagian besar objek ditugaskan ke area Eden terlebih dahulu, dan beberapa objek besar akan ditugaskan langsung ke generasi lama.
Frekuensi Frekuensi Daur Ulang: Karena sebagian besar objek generasi muda dengan cepat memasuki keadaan yang tidak terjangkau, frekuensi daur ulang tinggi dan kecepatan daur ulang cepat.
Generasi Generasi:
Mekanisme Pemeriksaan Siklus: Gunakan algoritma kompresi tanda untuk pulih.
Ⅱ Sumber objek: 1. Objek besar langsung memasuki usia tua.
2. Frekuensi daur ulang dari benda yang dapat dijangkau dengan waktu bertahan hidup yang lama pada generasi muda: karena beberapa objek mati, frekuensi eksekusi tidak tinggi dan butuh waktu lama untuk diselesaikan.
③ Generasi Saham:
ⅠPurpose: Digunakan untuk memuat kelas, metode, dan informasi lainnya. Standarnya adalah 64m dan tidak akan didaur ulang. ⅡObject Source: Misalnya: Untuk kerangka kerja seperti Hibernate dan Spring yang seperti kelas generasi dinamis AOP sering menghasilkan sejumlah besar kelas proxy dinamis, sehingga memori generasi yang lebih permanen diperlukan. Jadi kita sering menemukan java.lang.outofmemoryError: Permgen Space error saat men -debug hibernate. Ini adalah kesalahan yang disebabkan oleh kelelahan memori generasi permanen.
Ⅲ Frekuensi daur ulang: tidak akan didaur ulang
3.3 Kolektor Sampah Umum
1) Serial Recycler (hanya satu CPU yang digunakan): Generasi muda menggunakan algoritma salinan serial; Generasi Lama Menggunakan Algoritma Kompresi Mark Serial (Tiga Tahapan: Mark Mark - Clear Sweep - Compress Compact), program akan dijeda selama periode daur ulang.
2) Paralel Recycler: Algoritma yang digunakan untuk generasi muda adalah sama dengan pendaur ulang serial, tetapi hanya menambahkan pemrosesan paralel multi-CPU; Pemrosesan generasi lama persis sama dengan recycler serial, dan masih satu utas.
3) Kolektor Kompresi Paralel: Pemrosesan generasi muda adalah algoritma yang persis sama dengan pengumpul paralel; Tetapi algoritma yang berbeda digunakan untuk generasi lama, yang sebenarnya dibagi menjadi berbagai daerah dan kemudian pelabelan dan algoritma kompresi:
① Bagilah lama menjadi beberapa area tetap;
② Mark Stage (Multi-Threaded Parallel), menandai objek yang dapat dijangkau;
③ Tahap Ringkasan (Eksekusi Seri). Ketika Anda menemukan area yang mencapai nilai numerik (kepadatan objek rendah) dari kiri, area ini dan area kanannya dikompresi dan dipulihkan. Ujung kiri adalah area padat ④ tahap kompak (paralel multi-thread), mengidentifikasi area yang perlu dimuat, dan menyalin data ke area ini secara paralel. Setelah proses ini, ada sejumlah besar objek aktif di salah satu ujung generasi lama, dan sepotong besar ruang di ujung lainnya.
4) Identifikasi Bersamaan - Pembersihan dan Daur Ulang (CMS): Pemrosesan generasi muda adalah algoritma yang persis sama dengan pendaur ulang paralel; Tetapi algoritma yang berbeda digunakan untuk generasi lama, tetapi algoritma pembersihan tanda masih digunakan:
① Identifikasi awal (jeda program): menandai objek yang langsung direferensikan (objek tingkat pertama);
② Identifikasi Bersamaan (Program Run): Temukan objek lain yang dapat dijangkau melalui objek tingkat pertama;
③ Tanda ulang (jeda program): Objek penanda ulang paralel multi-thread yang mungkin terlewatkan karena konkurensi (hanya berbicara, ini anti-missing)
④ Pembersihan Bersamaan (program berjalan)
4. Kiat manajemen memori
1) Cobalah untuk menggunakan kuantitas langsung, misalnya: string javastr = "proses pertumbuhan magang sekolah dasar";
2) Gunakan StringBuilder dan StringBuffer untuk melakukan gabungan string dan operasi lainnya;
3) melepaskan objek yang tidak berguna sesegera mungkin;
4) Cobalah untuk menggunakan variabel statis sesedikit mungkin;
5) Cache Objek yang umum digunakan: dapat diimplementasikan menggunakan cache open source open source, misalnya: oscache, ehcache;
6) Cobalah untuk tidak menggunakan metode finalisasi ();
7) Anda dapat mempertimbangkan menggunakan softreference referensi lembut bila perlu.
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.