Manajemen Memori dalam Pertanyaan Wawancara Java (+ Jawaban)

Artikel ini adalah bagian dari serial: • Pertanyaan Wawancara Koleksi Java

• Pertanyaan Wawancara Sistem Jenis Java

• Pertanyaan Wawancara Konkurensi Java (+ Jawaban)

• Struktur Kelas Java dan Pertanyaan Wawancara Inisialisasi

• Java 8 Pertanyaan Wawancara (+ Jawaban)

• Manajemen Memori dalam Pertanyaan Wawancara Java (+ Jawaban) (artikel saat ini) • Pertanyaan Wawancara Umum Java (+ Jawaban)

• Pertanyaan Wawancara Kontrol Aliran Java (+ Jawaban)

• Pertanyaan Wawancara Pengecualian Jawa (+ Jawaban)

• Pertanyaan Wawancara Anotasi Jawa (+ Jawaban)

• Pertanyaan Wawancara Top Spring Framework

1. Perkenalan

Pada artikel ini, kita akan membahas beberapa pertanyaan manajemen memori yang sering muncul selama wawancara pengembang Java. Manajemen memori adalah area yang tidak begitu dikenal oleh banyak pengembang.

Faktanya, pengembang umumnya tidak harus berurusan dengan konsep ini secara langsung - karena JVM menangani detail seluk beluknya. Kecuali ada sesuatu yang tidak beres, bahkan pengembang berpengalaman mungkin tidak memiliki informasi akurat tentang manajemen memori di ujung jari mereka.

Di sisi lain, konsep ini sebenarnya cukup lazim dalam wawancara - jadi mari kita langsung masuk.

2. Pertanyaan

P1. Apa Arti Pernyataan "Memory Is Managed in Java"?

Memori adalah sumber daya kunci yang dibutuhkan aplikasi untuk berjalan secara efektif dan seperti sumber daya lainnya, memori langka. Dengan demikian, alokasi dan deallokasi ke dan dari aplikasi atau bagian aplikasi yang berbeda memerlukan banyak perhatian dan pertimbangan.

Namun, di Java, developer tidak perlu mengalokasikan dan membatalkan alokasi memori secara eksplisit - JVM dan lebih khusus lagi Garbage Collector - bertugas menangani alokasi memori sehingga developer tidak perlu melakukannya.

Hal ini bertentangan dengan apa yang terjadi dalam bahasa seperti C di mana programmer memiliki akses langsung ke memori dan secara harfiah mereferensikan sel memori dalam kodenya, menciptakan banyak ruang untuk kebocoran memori.

P2. Apa Itu Pengumpulan Sampah dan Apa Keuntungannya?

Pengumpulan sampah adalah proses melihat memori heap, mengidentifikasi objek mana yang sedang digunakan dan mana yang tidak, dan menghapus objek yang tidak digunakan.

Objek yang sedang digunakan, atau objek yang direferensikan, berarti bahwa beberapa bagian dari program Anda masih mempertahankan penunjuk ke objek tersebut. Objek yang tidak digunakan, atau objek yang tidak direferensikan, tidak lagi direferensikan oleh bagian mana pun dari program Anda. Jadi memori yang digunakan oleh objek yang tidak direferensikan dapat diperoleh kembali.

Keuntungan terbesar dari pengumpulan sampah adalah menghilangkan beban alokasi / deallocation memori manual dari kami sehingga kami dapat fokus pada penyelesaian masalah yang dihadapi.

P3. Apakah Ada Kerugian Mengumpulkan Sampah?

Iya. Setiap kali pengumpul sampah berjalan, itu berpengaruh pada kinerja aplikasi. Ini karena semua utas lain dalam aplikasi harus dihentikan untuk memungkinkan utas pengumpul sampah melakukan tugasnya secara efektif.

Bergantung pada persyaratan aplikasi, ini bisa menjadi masalah nyata yang tidak dapat diterima oleh klien. Namun, masalah ini bisa sangat dikurangi atau bahkan dihilangkan melalui pengoptimalan yang terampil dan penyetelan pengumpul sampah dan menggunakan algoritma GC yang berbeda.

P4. Apa Arti dari Istilah "Stop-The-World"?

Saat utas pengumpul sampah sedang berjalan, utas lain dihentikan, yang berarti aplikasi dihentikan sesaat. Ini serupa dengan pembersihan rumah atau pengasapan di mana penghuni tidak diberi akses sampai prosesnya selesai.

Bergantung pada kebutuhan aplikasi, pengumpulan sampah "hentikan dunia" dapat menyebabkan pembekuan yang tidak dapat diterima. Inilah mengapa penting untuk melakukan penyetelan pengumpul sampah dan pengoptimalan JVM agar pembekuan yang ditemui setidaknya dapat diterima.

P5. Apa itu Stack dan Heap? Apa yang Tersimpan dalam Masing-Masing Struktur Memori Ini, dan Bagaimana Mereka Berhubungan?

Tumpukan adalah bagian dari memori yang berisi informasi tentang panggilan metode bersarang ke posisi saat ini dalam program. Ini juga berisi semua variabel lokal dan referensi ke objek di heap yang ditentukan dalam metode yang saat ini dijalankan.

Struktur ini memungkinkan runtime untuk kembali dari metode dengan mengetahui alamat tempat pemanggilannya, dan juga menghapus semua variabel lokal setelah keluar dari metode. Setiap utas memiliki tumpukannya sendiri.

Heap adalah sebagian besar memori yang ditujukan untuk alokasi objek. Saat Anda membuat objek dengan kata kunci baru , itu akan dialokasikan di heap. Namun, referensi ke objek ini ada di tumpukan.

P6. Apa Itu Pengumpulan Sampah Generasi dan Apa yang Menjadikannya Pendekatan Pengumpulan Sampah yang Populer?

Pengumpulan sampah generasi dapat didefinisikan secara longgar sebagai strategi yang digunakan oleh pengumpul sampah di mana heap dibagi menjadi beberapa bagian yang disebut generasi, yang masing-masing akan menampung objek sesuai dengan "usia" di heap.

Setiap kali pengumpul sampah berjalan, langkah pertama dalam proses ini disebut menandai. Di sinilah pengumpul sampah mengidentifikasi bagian mana dari memori yang digunakan dan mana yang tidak. Ini bisa menjadi proses yang sangat memakan waktu jika semua objek dalam sistem harus dipindai.

Karena semakin banyak objek yang dialokasikan, daftar objek bertambah dan bertambah yang mengarah ke waktu pengumpulan sampah yang semakin lama. Namun, analisis empiris aplikasi telah menunjukkan bahwa sebagian besar objek berumur pendek.

Dengan pengumpulan sampah antargenerasi, objek dikelompokkan menurut "usianya" dalam hal berapa banyak siklus pengumpulan sampah yang bertahan. Dengan cara ini, sebagian besar pekerjaan tersebar di berbagai siklus pengumpulan kecil dan besar.

Saat ini, hampir semua pemulung merupakan generasi. Strategi ini begitu populer karena dari waktu ke waktu terbukti menjadi solusi yang optimal.

P7. Jelaskan secara Detail Cara Kerja Pengumpulan Sampah Generasi

Untuk memahami dengan benar cara kerja pengumpulan sampah generasi, pertama-tama penting untuk diingat bagaimana heap Java disusun untuk memfasilitasi pengumpulan sampah generasi.

Heap dibagi menjadi beberapa ruang atau generasi yang lebih kecil. Ruang-ruang tersebut adalah Generasi Muda, Generasi Tua atau Tenured, dan Generasi Permanen.

The host generasi muda sebagian besar objek yang baru dibuat . Sebuah studi empiris dari sebagian besar aplikasi menunjukkan bahwa mayoritas objek dengan cepat berumur pendek dan oleh karena itu, segera memenuhi syarat untuk koleksi. Oleh karena itu, objek baru memulai perjalanannya di sini dan hanya “dipromosikan” ke ruang generasi lama setelah mereka mencapai “usia” tertentu.

Istilah "usia" dalam pengumpulan sampah generasi mengacu pada jumlah siklus pengumpulan objek yang bertahan .

Ruang generasi muda selanjutnya dibagi menjadi tiga ruang: ruang Eden dan dua ruang penyintas seperti Survivor 1 (s1) dan Survivor 2 (s2).

The tua generasi host benda-benda yang telah hidup dalam memori lama dari “usia” tertentu . Benda-benda yang selamat dari pengumpulan sampah dari generasi muda dipromosikan ke ruang ini. Umumnya lebih besar dari generasi muda. Karena ukurannya yang lebih besar, pengumpulan sampah lebih mahal dan lebih jarang terjadi dibandingkan dengan generasi muda.

The generasi permanen atau lebih sering disebut, PermGen, berisi metadata yang dibutuhkan oleh JVM untuk menggambarkan kelas dan metode yang digunakan dalam aplikasi. Ini juga berisi kumpulan string untuk menyimpan string internal. Ini diisi oleh JVM saat runtime berdasarkan kelas yang digunakan oleh aplikasi. Selain itu, kelas dan metode pustaka platform dapat disimpan di sini.

Pertama, setiap objek baru dialokasikan ke ruang Eden . Kedua ruang penyintas mulai kosong. Saat ruang Eden terisi, pengumpulan sampah kecil dipicu. Objek yang direferensikan dipindahkan ke ruang survivor pertama. Objek yang tidak direferensikan dihapus.

Selama GC minor berikutnya, hal yang sama terjadi di ruang Eden. Objek yang tidak direferensikan dihapus dan objek yang direferensikan dipindahkan ke ruang survivor. Namun, dalam hal ini, mereka dipindahkan ke ruang survivor kedua (S2).

Selain itu, objek dari GC minor terakhir di ruang penyintas pertama (S1) bertambah usianya dan dipindahkan ke S2. Setelah semua benda yang masih hidup dipindahkan ke S2, baik ruang S1 dan Eden akan dikosongkan. Pada titik ini S2 berisi objek dengan umur yang berbeda.

Pada GC minor berikutnya, proses yang sama diulangi. Namun kali ini ruang penyintas beralih. Objek yang direferensikan dipindahkan ke S1 dari Eden dan S2. Benda yang bertahan sudah tua. Eden dan S2 dihapus.

Setelah setiap siklus pengumpulan sampah minor, usia setiap objek diperiksa. Mereka yang telah mencapai usia tertentu, misalnya 8, dipromosikan dari generasi muda ke generasi tua atau bertenor. Untuk semua siklus GC minor berikutnya, objek akan terus dipromosikan ke ruang generasi lama.

Ini cukup menguras proses pengumpulan sampah pada generasi muda. Akhirnya, pengumpulan sampah besar-besaran akan dilakukan pada generasi lama yang membersihkan dan memadatkan ruang itu. Untuk setiap GC mayor, ada beberapa GC minor.

P8. Kapan Suatu Objek Menjadi Memenuhi Syarat untuk Pengumpulan Sampah? Jelaskan Bagaimana Gc Mengumpulkan Objek yang Memenuhi Syarat?

Sebuah objek memenuhi syarat untuk pengumpulan Sampah atau GC jika tidak dapat dijangkau dari utas aktif apa pun atau oleh referensi statis apa pun.

Kasus paling mudah dari sebuah objek yang memenuhi syarat untuk pengumpulan sampah adalah jika semua referensinya adalah null. Dependensi siklik tanpa referensi eksternal langsung juga memenuhi syarat untuk GC. Jadi jika objek A mereferensikan objek B dan objek B mereferensikan Objek A dan mereka tidak memiliki referensi langsung lainnya maka Objek A dan B akan memenuhi syarat untuk pengumpulan Sampah.

Kasus lain yang jelas adalah ketika objek induk disetel ke nol. Jika objek dapur secara internal mereferensikan objek lemari es dan objek wastafel, dan objek dapur disetel ke nol, kulkas dan wastafel akan memenuhi syarat untuk pengumpulan sampah bersama dengan dapur induknya.

P9. Bagaimana Anda Memicu Pengumpulan Sampah dari Kode Java?

Anda, sebagai programmer Java, tidak bisa memaksa pengumpulan sampah di Java ; ini hanya akan terpicu jika JVM merasa perlu pengumpulan sampah berdasarkan ukuran heap Java.

Sebelum menghapus objek dari memori, thread pengumpulan sampah memanggil metode finalize () dari objek tersebut dan memberikan kesempatan untuk melakukan pembersihan apa pun yang diperlukan. Anda juga dapat menjalankan metode kode objek ini, namun, tidak ada jaminan bahwa pengumpulan sampah akan terjadi saat Anda memanggil metode ini.

Selain itu, ada metode seperti System.gc () dan Runtime.gc () yang digunakan untuk mengirim permintaan pengumpulan Sampah ke JVM tetapi tidak ada jaminan bahwa pengumpulan sampah akan terjadi.

P10. Apa Yang Terjadi Jika Tidak Ada Ruang Tumpukan Yang Cukup untuk Mengakomodasi Penyimpanan Objek Baru?

Jika tidak ada ruang memori untuk membuat objek baru di Heap, Java Virtual Machine akan menampilkan OutOfMemoryError atau lebih khusus lagi ruang heap java.lang.OutOfMemoryError .

P11. Mungkinkah «Menghidupkan Kembali» Objek yang Memenuhi Syarat untuk Pengumpulan Sampah?

Saat sebuah objek memenuhi syarat untuk pengumpulan sampah, GC harus menjalankan metode finalisasi padanya. The finalize metode dijamin untuk menjalankan hanya sekali, sehingga bendera GC objek sebagai diselesaikan dan memberikan istirahat sampai siklus berikutnya.

Dalam metode finalisasi, Anda secara teknis dapat "menghidupkan kembali" sebuah objek, misalnya, dengan menetapkannya ke bidang statis . Objek akan menjadi hidup kembali dan tidak memenuhi syarat untuk pengumpulan sampah, sehingga GC tidak akan mengumpulkannya pada siklus berikutnya.

Objek, bagaimanapun, akan ditandai sebagai selesai, jadi ketika itu akan memenuhi syarat lagi, metode finalisasi tidak akan dipanggil. Intinya, Anda dapat mengubah trik "kebangkitan" ini hanya sekali seumur hidup objek. Berhati-hatilah karena peretasan jelek ini harus digunakan hanya jika Anda benar-benar tahu apa yang Anda lakukan - namun, memahami trik ini memberikan beberapa wawasan tentang cara kerja GC.

P12. Jelaskan Referensi yang Kuat, Lemah, Lembut, dan Hantu serta Perannya dalam Pengumpulan Sampah.

Meskipun memori dikelola di Java, teknisi mungkin perlu melakukan pengoptimalan sebanyak mungkin untuk meminimalkan latensi dan memaksimalkan throughput, dalam aplikasi penting. Sebanyak itu tidak mungkin untuk secara eksplisit mengontrol kapan pengumpulan sampah dipicu dalam JVM, adalah mungkin untuk mempengaruhi bagaimana hal itu terjadi sebagai salam obyek yang kita buat.

Java memberi kita objek referensi untuk mengontrol hubungan antara objek yang kita buat dan pengumpul sampah.

Secara default, setiap objek yang kita buat di program Java sangat direferensikan oleh variabel:

StringBuilder sb = new StringBuilder();

Dalam potongan di atas, kata kunci baru membuat objek StringBuilder baru dan menyimpannya di heap. Variabel sb kemudian menyimpan referensi yang kuat ke objek ini. Artinya bagi pengumpul sampah adalah bahwa objek StringBuilder tertentu tidak memenuhi syarat untuk pengumpulan sama sekali karena referensi kuat yang dipegang oleh sb . Ceritanya hanya berubah ketika kita membatalkan sb seperti ini:

sb = null;

Setelah memanggil baris di atas, objek tersebut kemudian memenuhi syarat untuk dikumpulkan.

Kita bisa mengubah hubungan antara objek dan pengumpul sampah ini dengan membungkusnya secara eksplisit di dalam objek referensi lain yang terletak di dalam paket java.lang.ref .

Sebuah referensi yang lembut dapat dibuat untuk tujuan di atas seperti ini:

StringBuilder sb = new StringBuilder(); SoftReference sbRef = new SoftReference(sb); sb = null;

Dalam potongan di atas, kami telah membuat dua referensi ke objek StringBuilder . Baris pertama membuat sb referensi yang kuat dan baris kedua membuat referensi lunak sbRef . Baris ketiga harus membuat objek memenuhi syarat untuk dikumpulkan tetapi pengumpul sampah akan menunda pengumpulannya karena sbRef .

Cerita hanya akan berubah ketika memori menjadi sempit dan JVM berada di ambang kesalahan OutOfMemory . Dengan kata lain, objek dengan referensi lunak saja dikumpulkan sebagai upaya terakhir untuk memulihkan memori.

Sebuah referensi yang lemah dapat dibuat dengan cara yang sama menggunakan WeakReference kelas. Jika sb disetel ke null dan objek StringBuilder hanya memiliki referensi yang lemah, pengumpul sampah JVM sama sekali tidak akan berkompromi dan segera mengumpulkan objek tersebut di siklus berikutnya.

Sebuah referensi phantom mirip dengan referensi yang lemah dan objek dengan hanya referensi phantom akan dikumpulkan tanpa menunggu. Namun, referensi hantu diantrekan segera setelah objek mereka dikumpulkan. Kita bisa mengumpulkan antrian referensi untuk mengetahui dengan tepat kapan objek dikumpulkan.

P13. Misalkan Kita Memiliki Referensi Melingkar (Dua Objek Yang Saling Merujuk). Mungkinkah Pasangan Benda Tersebut Layak untuk Pengumpulan Sampah dan Mengapa?

Ya, sepasang objek dengan referensi melingkar dapat memenuhi syarat untuk pengumpulan sampah. Ini karena cara pengumpul sampah Java menangani referensi melingkar. Ini menganggap objek hidup bukan ketika mereka memiliki referensi ke mereka, tetapi ketika mereka dapat dijangkau dengan menavigasi grafik objek mulai dari beberapa akar pengumpulan sampah (variabel lokal dari utas langsung atau bidang statis). Jika sepasang objek dengan referensi melingkar tidak dapat dijangkau dari root mana pun, objek tersebut dianggap memenuhi syarat untuk pengumpulan sampah.

P14. Bagaimana String Diwakili dalam Memori?

Sebuah String contoh di Jawa adalah obyek dengan dua bidang: a nilai Char [] lapangan dan int hash lapangan. Bidang nilai adalah larik karakter yang mewakili string itu sendiri, dan bidang hash berisi kode hash dari string yang diinisialisasi dengan nol, dihitung selama panggilan hashCode () pertama dan di-cache sejak saat itu. Sebagai kasus edge yang aneh, jika hashCode dari sebuah string memiliki nilai nol, itu harus dihitung ulang setiap kali hashCode () dipanggil.

Hal yang penting adalah bahwa instance String tidak dapat diubah: Anda tidak bisa mendapatkan atau mengubah array char [] yang mendasarinya . Fitur lain dari string adalah bahwa string konstan statis dimuat dan di-cache dalam kumpulan string. Jika Anda memiliki beberapa objek String yang identik dalam kode sumber Anda, semuanya diwakili oleh satu instance pada waktu proses.

P15. Apa Itu Stringbuilder dan Apa Kasus Penggunaannya? Apa Perbedaan Antara Menambahkan String ke Stringbuilder dan Menggabungkan Dua String dengan Operator +? Apa Perbedaan Stringbuilder dari Stringbuffer?

StringBuilder memungkinkan manipulasi urutan karakter dengan menambahkan, menghapus, dan menyisipkan karakter dan string. Ini adalah struktur data yang dapat berubah, sebagai lawan dari kelas String yang tidak dapat diubah.

Saat menggabungkan dua instance String , objek baru dibuat, dan string disalin. Ini bisa membawa overhead pengumpul sampah yang sangat besar jika kita perlu membuat atau memodifikasi string dalam satu lingkaran. StringBuilder memungkinkan penanganan manipulasi string jauh lebih efisien.

StringBuffer berbeda dari StringBuilder karena aman untuk thread. Jika Anda perlu memanipulasi string dalam satu utas, gunakan StringBuilder sebagai gantinya.

3. Kesimpulan

Pada artikel ini, kami telah membahas beberapa pertanyaan paling umum yang sering muncul dalam wawancara insinyur Java. Pertanyaan tentang manajemen memori sebagian besar ditanyakan kepada kandidat Pengembang Java Senior karena pewawancara mengharapkan bahwa Anda telah membangun aplikasi non-sepele yang sering kali diganggu oleh masalah memori.

Ini tidak boleh diperlakukan sebagai daftar pertanyaan yang lengkap, melainkan landasan peluncuran untuk penelitian lebih lanjut. Kami, di Baeldung, berharap Anda sukses dalam wawancara yang akan datang.

Berikutnya » Pertanyaan Wawancara Generik Java (+ Jawaban) « Sebelumnya Java 8 Pertanyaan Wawancara (+ Jawaban)