1. Model memori java
Saat menjalankan program, mesin virtual Java membagi memori yang dikelola menjadi beberapa area data. Distribusi area data ini ditunjukkan pada gambar di bawah ini:
Penghitung Program: Area memori kecil yang menunjuk ke bytecode yang saat ini dieksekusi. Jika utas menjalankan metode Java, penghitung ini mencatat alamat instruksi bytecode mesin virtual yang dijalankan. Jika metode asli dijalankan, nilai kalkulator kosong.
Java Virtual Machine Stack: Thread bersifat pribadi, dan siklus hidupnya konsisten dengan benang. Ketika setiap metode dijalankan, bingkai tumpukan akan dibuat untuk menyimpan informasi seperti tabel variabel lokal, tumpukan operan, tautan dinamis, keluar metode, dll.
Tumpukan Metode Lokal: Fungsinya mirip dengan tumpukan mesin virtual, kecuali bahwa tumpukan mesin virtual melakukan layanan metode java untuk mesin virtual, sedangkan stack metode lokal melayani metode asli yang digunakan.
Java Heap: Ini adalah bagian terbesar dari memori manajemen mesin virtual, dibagikan oleh semua utas, area ini digunakan untuk menyimpan instance objek, dan hampir semua objek dialokasikan di area ini. Tumpukan Java adalah area utama daur ulang memori. Dari perspektif daur ulang memori, karena sebagian besar kolektor saat ini menggunakan algoritma koleksi generasi, tumpukan java juga dapat dibagi lagi menjadi: generasi baru dan generasi lama. Jika sedikit dibagi lagi, itu dapat dibagi menjadi ruang Eden, dari ruang survivor, ke ruang selamat, dll. Menurut spesifikasi mesin virtual Java, tumpukan java dapat berada dalam ruang terputus secara fisik, asalkan secara logis kontinu.
Area Metode: Seperti Java, ini dibagikan oleh berbagai utas dan digunakan untuk menyimpan data seperti informasi kelas yang telah dimuat oleh mesin virtual, selalu aktif, variabel statis, kode yang dikompilasi oleh kompiler instan.
Runtime Constant Pool, Runtime Constant Pool adalah bagian dari area metode. Selain versi kelas, bidang, metode, antarmuka, dan informasi deskripsi lainnya, ada juga kumpulan konstan dalam file kelas, yang digunakan untuk menyimpan berbagai referensi literal dan simbolik yang dihasilkan selama periode kompilasi. Selama runtime, konstanta baru dapat ditempatkan di kolam konstan. Metode magang () dari kelas string. Ketika instance string memanggil magang, Java menemukan apakah ada konstanta string unicode yang sama di kumpulan konstan. Jika ada, ia mengembalikan rujukannya; Jika tidak, tambahkan unicode yang sama dengan string instance dan mengembalikan referensi.
2. Cara menentukan objek sampah
Ada beberapa contoh objek yang disimpan di tumpukan Java. Sebelum pengumpul sampah mendaur ulang tumpukan, pertama -tama perlu menentukan benda mana yang masih "hidup" dan mana yang "mati", yaitu objek yang tidak akan digunakan dengan cara apa pun.
Menghitung kutipan
Metode penghitungan kutipan mudah diimplementasikan dan secara efisien, dan merupakan algoritma yang baik dalam banyak kasus. Prinsipnya adalah: tambahkan penghitung referensi ke objek. Setiap kali ada tempat untuk merujuk objek, penghitung ditingkatkan dengan 1. Ketika referensi gagal, penghitung dikurangi dengan 1. Ketika nilai penghitung adalah 0, itu berarti bahwa objek tidak lagi digunakan. Perlu dicatat bahwa metode penghitungan referensi sulit untuk menyelesaikan masalah referensi timbal balik antara objek, dan mesin virtual Java utama tidak menggunakan metode penghitungan referensi untuk mengelola memori.
Algoritma Analisis Aksesibilitas
Gagasan dasar dari algoritma ini adalah mencari ke bawah melalui serangkaian objek yang disebut "GC Roots" sebagai titik awal, mulai dari node ini. Jalur yang dicari disebut rantai referensi. Ketika suatu objek tidak terhubung ke akar GC tanpa rantai referensi (dalam kata -kata teori grafik, itu dari akar GC ke objek ini yang tidak dapat dijangkau), terbukti bahwa objek ini tidak tersedia. Seperti yang ditunjukkan pada gambar, meskipun Objek 5, Objek 6, dan Objek 7 saling terkait, mereka tidak dapat dijangkau dengan akar GC, sehingga mereka akan dinilai sebagai objek yang dapat didaur ulang.
Dalam bahasa Java, objek berikut yang dapat digunakan sebagai akar GC termasuk:
Objek yang dirujuk dalam tumpukan mesin virtual (tabel variabel lokal di bingkai tumpukan).
Objek dirujuk oleh atribut statis kelas di area metode.
Objek yang dirujuk oleh konstanta di area metode.
Objek yang dirujuk oleh JNI (yaitu, metode asli asli) dalam Stack Metode Lokal.
Sekarang pertanyaannya adalah, akankah algoritma analisis aksesibilitas memiliki masalah referensi melingkar antara objek? Jawabannya adalah ya, yaitu, tidak akan ada masalah referensi melingkar antar objek. Root GC adalah "titik awal" yang didefinisikan secara khusus di luar grafik objek dan tidak dapat direferensikan oleh objek dalam grafik objek.
Mati atau tidak mati
Bahkan objek yang tidak dapat dijangkau dalam algoritma analisis aksesibilitas tidak "harus mati". Pada saat ini, mereka sementara berada dalam tahap "masa percobaan". Untuk benar -benar mendeklarasikan objek yang mati, itu harus melalui setidaknya dua proses penandaan: Jika objek menemukan bahwa tidak ada rantai referensi yang terhubung ke akar GC setelah melakukan analisis aksesibilitas, itu akan ditandai untuk pertama kalinya dan disaring. Kondisi penyaringan adalah apakah perlu untuk objek ini untuk menjalankan metode finapze (). Ketika objek tidak menimpa metode finapze (), atau metode finapze () telah dipanggil oleh mesin virtual, mesin virtual menganggap kedua kasus sebagai "tidak perlu dieksekusi". Dalam program ini, Anda dapat menimpa Finapze () untuk membuat proses penyalaan diri yang "mendebarkan", tetapi ini hanya satu peluang.
/** * Kode ini menunjukkan dua poin: * 1. Objek dapat menyelamatkan diri ketika mereka GC. * 2. Hanya ada satu peluang untuk menyelamatkan diri, karena metode finapze () suatu objek hanya akan secara otomatis dipanggil sekali oleh sistem paling banyak * @author zzm */ pubpc kelas finapzeescapegc {pubpc static finapzeescapegc save_hook = null; pubpc void isapve () {System.out.println ("Ya, saya masih apve :)"); } @Override Protected void finapze () melempar lempar {super.finapze (); System.out.println ("Finapze Mehtod dieksekusi!"); Finapzeescapegc.save_hook = ini; } pubpc static void main (string [] args) melempar lempar {save_hook = new finapzeescapegc (); // Objek berhasil menyelamatkan dirinya untuk pertama kalinya save_hook = null; System.gc (); // Karena metode Finapze memiliki prioritas rendah, jeda selama 0,5 detik untuk menunggu thread.sleep (500); if (save_hook! = null) {save_hook.isapve (); } else {System.out.println ("Tidak, saya mati :(");} // Kode berikut persis sama dengan yang di atas, tetapi kali ini penyelamatan diri gagal. Save_hook = null; System.gc (); // karena metode finapze memiliki prioritas rendah, ia berhenti untuk 0,5 detik untuk menunggu. Save_hook.isapve ();} else {System.out.println ("Tidak, saya mati :(");}}Hasil berjalan adalah:
Finapze Mehtod dieksekusi! ya, saya masih apve :) tidak, saya mati :(
Mari Bicara Tentang Kutipan
Apakah ia menilai jumlah referensi suatu objek melalui algoritma penghitungan referensi atau menentukan apakah rantai referensi objek dapat dicapai melalui algoritma analisis aksesibilitas, menentukan apakah kelangsungan hidup objek terkait dengan "referensi". Sebelum JDK 1.2, definisi referensi di Java sangat tradisional: jika nilai yang disimpan dalam data jenis referensi mewakili alamat awal dari bagian memori lain, dikatakan bahwa bagian memori ini mewakili referensi. Setelah JDK 1.2, Java memperluas konsep referensi, dan membagi referensi menjadi empat jenis: referensi yang kuat, referensi lunak, referensi lemah, dan referensi hantu. Kekuatan dari keempat jenis referensi ini secara bertahap melemah pada gilirannya.
• Kutipan yang kuat mengacu pada referensi yang umum dalam kode program, seperti "objek obj = objek baru ()". Selama kutipan yang kuat masih ada, pengumpul sampah tidak akan pernah mendaur ulang objek yang dirujuk.
• Referensi lunak digunakan untuk menggambarkan beberapa objek yang berguna tetapi tidak perlu. Untuk objek terkait referensi lunak, objek ini akan tercantum dalam ruang lingkup daur ulang untuk daur ulang kedua sebelum sistem akan memiliki pengecualian meluap memori. Jika tidak ada cukup memori untuk daur ulang ini, pengecualian overflow memori akan dilemparkan. Setelah JDK 1.2, kelas Softreference disediakan untuk mengimplementasikan referensi lunak.
• Referensi yang lemah juga digunakan untuk menggambarkan objek yang tidak penting, tetapi kekuatannya lebih lemah dari referensi lunak. Objek yang terkait dengan referensi yang lemah hanya dapat bertahan hidup sampai pengumpulan sampah berikutnya terjadi. Ketika pengumpul sampah bekerja, objek yang hanya dikaitkan dengan referensi yang lemah dikumpulkan terlepas dari apakah memori saat ini cukup. Setelah JDK 1.2, kelas Lemah Referensi disediakan untuk menerapkan referensi yang lemah.
• Kutipan batal juga disebut kutipan hantu atau kutipan hantu, dan mereka adalah hubungan kutipan terlemah. Apakah suatu objek memiliki referensi virtual tidak akan berdampak pada waktu kelangsungan hidupnya sama sekali, juga tidak mungkin untuk mendapatkan instance objek melalui referensi virtual. Satu -satunya tujuan pengaturan asosiasi referensi virtual untuk suatu objek adalah untuk menerima pemberitahuan sistem ketika objek didaur ulang oleh kolektor. Setelah JDK 1.2, kelas phantomreference disediakan untuk mengimplementasikan referensi virtual.
Contoh penggunaan referensi lunak:
Paket JVM; Impor java.lang.ref.softreference; class node {pubpc string msg = "";} kelas pubpc hello {pubpc static void main (string [] args) {node node1 = new node (); // referensi kuat node1.msg = "node1"; softreference <node> node2 = softreference baru <node> (node1); // referensi lunak node2.get (). Msg = "node2"; system.out.println (node1.msg); System.out.println (node2.get (). Msg);}}Hasil outputnya adalah:
node2node2
3. Algoritma Koleksi Sampah Khas
1. Mark-Sweep (Mark-Clear) Algoritma
Ini adalah algoritma pengumpulan sampah paling dasar. Alasan mengapa dikatakan sebagai yang paling mendasar adalah bahwa itu adalah yang termudah untuk diterapkan dan ide paling sederhana. Algoritma pembersihan tanda dibagi menjadi dua tahap: tahap tanda dan tahap kliring. Tugas tahap penandaan adalah untuk menandai semua objek yang perlu didaur ulang, dan tahap kliring adalah mendaur ulang ruang yang ditempati oleh benda -benda yang ditandai. Proses spesifik ditunjukkan pada gambar di bawah ini:
Dapat dengan mudah dilihat dari gambar bahwa algoritma pembersihan tanda lebih mudah diimplementasikan, tetapi ada masalah serius bahwa mudah untuk menghasilkan fragmen memori. Terlalu banyak fragmen dapat menyebabkan ketidakmampuan menemukan ruang yang cukup saat mengalokasikan ruang untuk objek besar dalam proses berikutnya, dan memicu tindakan pengumpulan sampah baru terlebih dahulu.
2. Menyalin algoritma
Untuk memecahkan kekurangan algoritma Mark-Sweep, algoritma penyalinan diusulkan. Ini membagi memori yang tersedia menjadi dua potong dengan ukuran yang sama berdasarkan kapasitas, hanya menggunakan satu bagian sekaligus. Ketika bagian memori ini digunakan, salin objek yang masih hidup ke bagian lain, dan kemudian bersihkan ruang memori yang digunakan sekaligus, sehingga masalah fragmentasi memori tidak akan terjadi. Proses spesifik ditunjukkan pada gambar di bawah ini:
Meskipun algoritma ini mudah diimplementasikan, efisien untuk dijalankan dan tidak mudah untuk menghasilkan fragmentasi memori, mahal untuk menggunakan ruang memori karena memori yang dapat digunakan dikurangi menjadi setengah dari yang asli.
Jelas, efisiensi algoritma penyalinan ada hubungannya dengan jumlah benda yang masih ada. Jika ada banyak objek yang masih hidup, efisiensi algoritma penyalinan akan sangat berkurang.
3. Algoritma Mark-Compact (Mark-Collation)
Untuk menyelesaikan kekurangan algoritma penyalinan dan memanfaatkan sepenuhnya ruang memori, algoritma kompak tanda-markus diusulkan. Algoritme menandai sama dengan Mark-Sheep, tetapi setelah menyelesaikan tanda, itu tidak secara langsung membersihkan objek yang dapat didaur ulang, tetapi menggerakkan semua benda hidup ke satu ujung dan kemudian membersihkan memori di luar batas ujung. Proses spesifik ditunjukkan pada gambar di bawah ini:
4. Algoritma Koleksi Generasi
Algoritma Generation Collection saat ini digunakan oleh sebagian besar kolektor sampah JVM. Gagasan intinya adalah membagi memori menjadi beberapa daerah yang berbeda sesuai dengan siklus hidup kelangsungan hidup objek. Secara umum, area tumpukan dibagi menjadi generasi lama dan generasi muda. Karakteristik generasi lama adalah bahwa hanya sejumlah kecil objek yang perlu didaur ulang setiap kali sampah dikumpulkan, sedangkan karakteristik generasi baru adalah bahwa sejumlah besar objek perlu didaur ulang setiap kali sampah dikumpulkan. Kemudian algoritma pengumpulan yang paling cocok dapat diadopsi sesuai dengan karakteristik generasi yang berbeda.
Saat ini, sebagian besar pengumpul sampah mengadopsi algoritma penyalinan untuk generasi baru, karena pada generasi baru, sebagian besar objek perlu didaur ulang setiap saat, yaitu, jumlah operasi yang perlu disalin kecil, tetapi dalam kenyataannya, ruang generasi baru tidak dibagi sesuai dengan rasio 1: 1. Secara umum, generasi baru dibagi menjadi ruang eden yang lebih besar dan dua ruang penyintas yang lebih kecil (biasanya 8: 1: 1). Setiap kali ruang Eden dan salah satu ruang yang selamat digunakan, ketika mendaur ulang, benda -benda yang masih bertahan di Eden dan Survivor disalin ke ruang korban lainnya, dan kemudian Eden dan ruang yang selamat yang baru saja digunakan dibersihkan.
Karena usia tua adalah bahwa hanya sejumlah kecil objek yang didaur ulang setiap saat, algoritma kompak tanda-markus umumnya digunakan.
Analisis singkat di atas model memori Java dan koleksi sampah adalah semua konten yang saya bagikan dengan Anda. Saya harap Anda dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.