Seorang programmer Java yang sangat baik harus memahami cara kerja GC, cara mengoptimalkan kinerja GC, dan bagaimana memiliki interaksi terbatas dengan GC, karena beberapa aplikasi memiliki persyaratan kinerja tinggi, seperti sistem tertanam, sistem waktu nyata, dll., Yang hanya bisa terjadi peningkatan secara komprehensif. Artikel ini pertama kali memperkenalkan prinsip kerja GC, kemudian melakukan diskusi mendalam tentang beberapa masalah utama GC, dan akhirnya mengajukan beberapa saran pemrograman Java untuk meningkatkan kinerja program Java dari perspektif GC.
Prinsip -prinsip dasar GC
Manajemen memori Java sebenarnya adalah manajemen objek, termasuk alokasi dan pelepasan objek.
Untuk pemrogram, kata kunci baru digunakan untuk mengalokasikan objek; .Gc akan bertanggung jawab untuk merebut kembali ruang memori dari semua /"tidak terjangkau /" objek.
Untuk GC, ketika seorang programmer membuat objek, GC mulai memantau alamat, ukuran, dan penggunaan objek. Secara umum, GC menggunakan grafik terarah untuk merekam dan mengelola semua objek di heap (heap) (lihat referensi 1 untuk detail). Dengan cara ini, objek mana yang bisa /"dapat dijangkau /" dan objek mana yang tidak dapat dijangkau /". Ketika GC menentukan bahwa beberapa objek adalah /" tidak terjangkau /", GC bertanggung jawab untuk mengklaim kembali ruang memori ini. Namun, untuk memastikan bahwa GC dapat diimplementasikan pada platform yang berbeda, spesifikasi Java tidak sepenuhnya menetapkan banyak perilaku GC. Misalnya, tidak ada peraturan yang jelas tentang masalah -masalah penting seperti jenis algoritma daur ulang apa yang akan digunakan dan kapan melakukan daur ulang. Oleh karena itu, pelaksana JVM yang berbeda sering memiliki algoritma implementasi yang berbeda. Ini juga membawa ketidakpastian bagi pengembangan programmer Java. Artikel ini membahas beberapa masalah yang berkaitan dengan pekerjaan GC dan berusaha untuk mengurangi dampak negatif dari ketidakpastian ini pada program Java.
Incremental GC (Incremental GC)
GC biasanya diimplementasikan dalam JVM oleh satu atau sekelompok proses. Oleh karena itu, ketika GC berjalan untuk waktu yang lama, pengguna dapat merasakan jeda program Java. Masih banyak objek yang harus didaur ulang yang belum didaur ulang. Oleh karena itu, saat merancang GC, perlu untuk menimbang waktu jeda dan tingkat pemulihan. Implementasi GC yang baik memungkinkan pengguna untuk menentukan pengaturan yang mereka butuhkan. Game online real-time lainnya tidak dapat memungkinkan gangguan jangka panjang pada program. GC tambahan adalah untuk membagi interupsi jangka panjang menjadi banyak interupsi kecil melalui algoritma daur ulang tertentu, sehingga mengurangi dampak GC pada program pengguna. Meskipun GC tambahan mungkin tidak seefisien GC reguler dalam kinerja keseluruhan, ini dapat mengurangi waktu jeda maksimum program.
JVM hotspot yang disediakan oleh Sun JDK dapat mendukung GC Incremental. Implementasi Hotspot JVM Incremental GC adalah menggunakan algoritma kereta GC. Gagasan dasarnya adalah untuk mengelompokkan semua objek di tumpukan (secara hierarkis) sesuai dengan penciptaan dan penggunaan, menempatkan objek dengan penggunaan yang sering dan sangat relevan dalam antrian, dan terus mengelompokkan saat program menjalankan penyesuaian. Ketika GC berjalan, itu selalu mendaur ulang objek tertua (jarang dikunjungi baru -baru ini) terlebih dahulu, dan jika seluruh grup adalah objek yang dapat didaur ulang, GC mendaur ulang seluruh grup. Dengan cara ini, setiap menjalankan GC hanya akan mendaur ulang proporsi tertentu dari objek yang tidak dapat dijangkau untuk memastikan kelancaran operasi program.
Penjelasan terperinci tentang fungsi finalisasi
Finalisasi adalah metode yang terletak di kelas objek. Karena fungsi finalisasi tidak secara otomatis menerapkan panggilan rantai, kita harus mengimplementasikannya secara manual, sehingga pernyataan terakhir dari fungsi finalisasi biasanya super.finalisasi (). Dengan cara ini, kami dapat menerapkan panggilan untuk mengimplementasikan finalisasi dari bawah ke atas, yaitu, pertama -tama merilis sumber daya kami sendiri, dan kemudian melepaskan sumber daya kelas induk.
Menurut spesifikasi bahasa Java, JVM memastikan bahwa objek ini tidak dapat dijangkau sebelum memanggil fungsi finalisasi, tetapi JVM tidak menjamin bahwa fungsi ini akan dipanggil. Selain itu, spesifikasi juga memastikan bahwa fungsi finalisasi paling banyak berjalan sekali.
Banyak pemula Java akan berpikir bahwa metode ini mirip dengan destruktor di C ++, dan menempatkan pelepasan banyak objek dan sumber daya dalam fungsi ini. Sebenarnya, ini bukan cara yang baik. Ada tiga alasan. Kedua, setelah finalisasi menjalankan selesai, objek dapat dijangkau, dan GC perlu memeriksa lagi apakah objek tersebut dapat dijangkau. Oleh karena itu, menggunakan finalisasi akan mengurangi kinerja GC. Ketiga, sejak saat panggilan GC finalisasi tidak pasti, juga tidak pasti untuk melepaskan sumber daya dengan cara ini.
Secara umum, finalisasi digunakan untuk melepaskan beberapa sumber daya yang tidak mudah dikendalikan dan sangat penting, seperti beberapa operasi I/O dan koneksi data. Rilis sumber daya ini sangat penting untuk seluruh aplikasi. Dalam hal ini, programmer terutama harus mengelola sumber daya ini melalui program itu sendiri (termasuk pelepasan) dan melengkapi metode melepaskan sumber daya dengan fungsi finalisasi sebagai suplemen untuk membentuk mekanisme manajemen asuransi ganda, daripada hanya mengandalkan finalisasi untuk melepaskan sumber daya.
Berikut adalah contoh untuk mengilustrasikan bahwa setelah fungsi finalisasi disebut, itu mungkin masih dapat dijangkau.
class myObject {test main; // Rekam objek tes, digunakan untuk mengembalikan aksesibilitas saat dalam menyelesaikan myObject publik (tes t) {main = t; /Kembalikan objek ini sehingga objek ini dapat mencapai System.out.println (/"Ini finalisasi/"); // Digunakan untuk menguji finalisasi untuk menjalankan hanya sekali}} tes kelas {myObject ref; ] ARGS) {Test Test = New Test (); .ref! = null) System.out.println (/"Objek saya masih hidup/");
Hasil Menjalankan:
Ini sudah selesai
MyObject masih hidup
Dalam contoh ini, perlu dicatat bahwa meskipun objek MyObject menjadi objek yang dapat dijangkau dalam finalisasi, lain kali Anda mendaur ulang, finalisasi tidak akan lagi dipanggil karena fungsi finalisasi hanya dipanggil sekali paling banyak.
Bagaimana program berinteraksi dengan GC
Java2 meningkatkan fungsi manajemen memori dan menambahkan paket java.lang.ref, yang mendefinisikan tiga kelas referensi. Tiga kelas referensi ini adalah Softreference, Weakreference dan Phantomreference. Kekuatan referensi dari kelas referensi ini adalah antara objek yang dapat dijangkau dan tidak dapat dijangkau.
Juga sangat mudah untuk membuat objek referensi Atur referensi normal ke nol. Pada saat yang sama, kami menyebut objek ini objek referensi yang lembut.
Fitur utama dari referensi lunak adalah ia memiliki fungsi kutipan yang kuat. Jenis memori ini didaur ulang hanya ketika ada memori yang tidak mencukupi, jadi ketika ada memori yang cukup, mereka biasanya tidak didaur ulang. Selain itu, objek referensi ini juga dapat diatur ke nol sebelum Java melempar pengecualian outofmemory Berikut ini adalah berikut penggunaan pseudocode untuk jenis referensi ini;
// Aplikasi Gambar objek gambar = gambar baru (); // Buat objek gambar ... // Gunakan gambar ... // Setelah menggunakan gambar, atur ke jenis referensi lunak, dan lepaskan referensi yang kuat; = Softreference baru (gambar); itu perlu diisi ulang;
Perbedaan terbesar antara objek referensi yang lemah dan objek referensi lunak adalah bahwa ketika GC mendaur ulang, ia perlu menggunakan algoritma untuk memeriksa apakah objek referensi lunak didaur ulang, sementara GC selalu mendaur ulang objek referensi yang lemah. Objek referensi yang lemah lebih mudah dan lebih cepat untuk didaur ulang oleh GC. Meskipun GC harus mendaur ulang objek yang lemah saat berlari, sekelompok objek lemah dengan hubungan yang kompleks seringkali membutuhkan beberapa run GC untuk diselesaikan. Objek referensi yang lemah sering digunakan dalam struktur peta untuk merujuk ke objek dengan volume data yang besar.
Referensi hantu kurang berguna dan terutama digunakan untuk membantu dalam penggunaan fungsi finalisasi. Objek hantu merujuk pada beberapa objek yang telah menyelesaikan fungsi finalisasi dan merupakan objek yang tidak dapat dijangkau, tetapi mereka belum didaur ulang oleh GC. Objek semacam ini dapat membantu menyelesaikan beberapa pekerjaan daur ulang kemudian.
Beberapa saran pengkodean java
Menurut prinsip kerja GC, kita dapat menggunakan beberapa keterampilan dan metode untuk membuat GC berjalan lebih efisien dan lebih sesuai dengan persyaratan aplikasi. Berikut adalah beberapa saran untuk pemrograman.
1. Saran yang paling mendasar adalah melepaskan referensi objek yang tidak berguna sesegera mungkin. Ketika sebagian besar pemrogram menggunakan variabel sementara, mereka akan secara otomatis mengatur variabel referensi ke nol setelah keluar dari domain aktif (ruang lingkup). Ketika kita menggunakan metode ini, kita harus memberikan perhatian khusus pada beberapa grafik objek yang kompleks, seperti array. Grafik, dll., Memiliki hubungan yang kompleks antara objek -objek ini. Untuk objek seperti itu, GC mendaur ulangnya umumnya kurang efisien. Jika program mengizinkannya, tetapkan objek referensi yang tidak digunakan untuk NULL sesegera mungkin. [Halaman]
2. Coba gunakan fungsi finalisasi sesedikit mungkin. Fungsi finalisasi adalah peluang bagi Java untuk memberi para programmer kesempatan untuk melepaskan objek atau sumber daya. Namun, itu akan meningkatkan beban kerja GC, jadi cobalah untuk menggunakan finalisasi sesedikit mungkin untuk mendaur ulang sumber daya.
3. Jika Anda perlu menggunakan gambar yang sering digunakan, Anda dapat menggunakan jenis aplikasi lunak. Ini dapat menyimpan gambar dalam memori sebanyak mungkin untuk dihubungi program tanpa menyebabkan outofmemory.
4. Perhatikan tipe data pengumpulan, termasuk struktur data seperti array, pohon, grafik, dan daftar tertaut. Juga, perhatikan beberapa variabel global, serta beberapa variabel statis. Variabel -variabel ini cenderung dengan mudah menyebabkan referensi yang menggantung, menyebabkan limbah memori.
5. Ketika program memiliki waktu tunggu tertentu, programmer dapat secara manual menjalankan System.gc () untuk memberi tahu GC untuk dijalankan, tetapi spesifikasi bahasa Java tidak menjamin bahwa GC akan mengeksekusi. Menggunakan GC tambahan dapat mempersingkat waktu jeda program Java.