Berbagi teknologi

Pertanyaan wawancara 005-Java-JVM (Bagian 1)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Pertanyaan wawancara 005-Java-JVM (Bagian 1)

Pertanyaan tes mandiri

  • 1. JVM terdiri dari bagian apa?
  • 2. Area apa saja yang termasuk dalam area data runtime?
  • 3. Data apa yang masing-masing disimpan di stack dan heap?
  • 4. Mengapa kita harus mengganti generasi permanen (PermGen) dengan metaspace (MetaSpace)?
  • 5. Apakah Anda memahami struktur dasar ruang heap? Dalam keadaan apa suatu benda akan masuk ke generasi lama?
  • 6. Di area memori manakah benda berukuran besar ditempatkan?
  • 7. Bagaimana proses pembuatan objek Java?

Jawaban pertanyaan

1. JVM terdiri dari bagian apa?

Jawaban: JVM dapat dieksekusikode byte (.class) file komputer virtual, yang juga menyediakan manajemen memori, pengumpulan sampah, dan mekanisme lainnya. Ini berisi bagian utama berikut.

  • Subsistem pemuatan kelas: Bertanggung jawab untuk memuat file bytecode (.class) ke dalam JVM.
  • Area data runtime: adalah area memori yang digunakan oleh JVM selama eksekusi.
  • Mesin eksekusi: Bertanggung jawab untuk menafsirkan atau menyusun bytecode menjadi kode mesin untuk eksekusi prosesor.
  • Antarmuka perpustakaan asli: Menyediakan serangkaian API untuk memanggil perpustakaan asli yang ditulis dalam sistem operasi atau bahasa lain.

2. Area apa saja yang termasuk dalam area data runtime?

Jawaban: Area data runtime adalah area memori yang dialokasikan oleh JVM saat menjalankan program Java.

  • Penghitung program: Ini adalah ruang memori kecil dan merupakan alamat instruksi bytecode yang saat ini dijalankan oleh thread. Jika thread menjalankan metode asli, nilai penghitung ini tidak ditentukan.
  • Tumpukan mesin virtual Java: Setiap thread akan membuat tumpukan mesin virtual saat dibuat, yang digunakan untuk menyimpan tabel variabel lokal thread, bingkai operan, tautan dinamis, informasi keluar metode, dll. Tumpukan mesin virtual Java berisi beberapa bingkai tumpukan. Proses dari setiap metode yang dipanggil hingga penyelesaian eksekusi sesuai dengan proses dari mendorong bingkai tumpukan ke dalam tumpukan di mesin virtual.
  • Tumpukan metode asli: Ini adalah ruang yang disiapkan oleh JVM untuk menjalankan metode Asli. Ini memiliki fungsi yang mirip dengan tumpukan mesin virtual Java.
  • Heap: digunakan untuk menyimpan hampir semua instance objek dan array, dan merupakan area utama tempat kerja pengumpul sampah.
  • Area metode: digunakan untuk menyimpan informasi kelas, konstanta, variabel statis, kode yang dikompilasi oleh kompiler just-in-time, dll. yang dimuat oleh JVM. Sebelum JDK1.8, ini diimplementasikan sebagai generasi permanen. Mulai dari JDK1.8, generasi permanen digantikan oleh ruang aslinya. Metaspace menggunakan memori lokal daripada memori heap.
    Area data runtime mesin virtual Java

3. Data apa yang masing-masing disimpan di stack dan heap?

Jawaban: Data disimpan dalam tumpukan (tumpukan mesin virtual Java):

  • Tabel variabel lokal: Terutama digunakan untuk menyimpan parameter metode dan variabel lokal dalam metode. Tipe data mencakup tipe data dasar dan referensi objek.
  • Tumpukan operan: digunakan untuk menyimpan sementara instruksi operasi dan hasil antara selama eksekusi metode.
  • Tautan dinamis: Referensi ke kumpulan konstan kelas tempat metode tersebut berada, digunakan untuk menyelesaikan referensi simbol dalam metode tersebut.
  • Alamat pengembalian metode: menyimpan alamat instruksi berikutnya yang dieksekusi setelah pemanggilan metode.
    Data yang disimpan di tumpukan:
  • Contoh objek: Contoh objek yang dibuat melalui kata kunci baru dalam program, termasuk properti dan metode objek.
  • Array: Semua tipe array, termasuk array tipe dasar dan array objek.

4. Mengapa kita harus mengganti generasi permanen (PermGen) dengan metaspace (MetaSpace)?

Jawaban: Mengganti generasi permanen dengan metaspace terutama untuk memecahkan beberapa masalah yang melekat dan keterbatasan generasi permanen serta meningkatkan kinerja dan fleksibilitas JVM.

  • Meningkatkan fleksibilitas dan efisiensi manajemen memori: Ukuran memori generasi permanen diatur saat JVM dimulai dan tidak dapat disesuaikan secara dinamis. Metaspace menggunakan memori lokal, bukan memori heap Java, dan ukurannya dapat disesuaikan secara dinamis sesuai kebutuhan.
  • Memecahkan masalah pembongkaran kelas dan pengumpulan sampah: perilaku GC pada pembangkitan permanen rumit dan tidak dapat diprediksi, serta efisiensi daur ulangnya rendah.
  • Memberikan kinerja dan stabilitas yang lebih baik: Menggunakan metaspace membuat manajemen memori JVM lebih terpadu dan konsisten, karena metaspace, seperti area memori lainnya, dikelola menggunakan memori lokal. Ini menyederhanakan strategi manajemen memori dan meningkatkan kinerja dan stabilitas secara keseluruhan.
  • Sederhanakan manajemen memori JVM

5. Apakah Anda memahami struktur dasar ruang heap? Dalam keadaan apa suatu benda akan masuk ke generasi lama?

Jawaban: Struktur dasar heap space sebagian besar terdiri dari generasi baru, generasi lama, dan generasi permanen. Setelah JDK8, generasi permanen digantikan oleh metaspace dan menggunakan memori lokal untuk penyimpanan.

  • Generasi Kenozoikum: Kemajuan generasi baru dibagi lagi menjadi kawasan Eden dan dua kawasan penyintas (Survivor 0 dan Survivor 1)
    • Area Eden: Objek yang baru dibuat pertama-tama mengalokasikan memori di area Eden.
    • Survivor area (S0, S1): digunakan untuk menyimpan benda-benda yang selamat dari pengumpulan sampah generasi baru. Setelah setiap Minor GC, objek yang masih ada akan disalin bolak-balik antara dua area ini.
  • Generasi lama: Objek yang masih hidup setelah beberapa GC Minor. Pengumpulan sampah (GC Utama atau GC Penuh) lebih jarang dilakukan pada generasi lama.
  • Generasi permanen/metaspace: digunakan untuk menyimpan metadata kelas, termasuk definisi kelas, konstanta, variabel statis, kode kompilasi just-in-time, dll.

Situasi ketika objek berada di generasi lama:

  • Ambang batas usia tercapai: Setiap objek memiliki usia ketika memori dialokasikan pada generasi baru, dan usia akan bertambah 1 setelah setiap Minor GC. Ketika usia mencapai ambang batas tertentu (defaultnya adalah 15), objek tersebut akan dipromosikan ke generasi lama.
  • Objek besar: Jika objek terlalu besar dan melebihi ambang batas yang ditetapkan oleh JVM, objek akan langsung mengalokasikan ruang pada generasi lama.
  • Ruang yang tidak mencukupi di area Survivor: Jika area penyintas tidak memiliki cukup ruang untuk menampung semua objek yang bertahan selama Minor GC, objek tersebut akan dirusak.
  • Penentuan usia objek dinamis: Jika ukuran semua objek dengan usia yang sama di ruang Survivor melebihi setengah dari ruang Survivor, maka objek yang usianya lebih besar atau sama dengan usia tersebut dapat langsung masuk ke generasi lama.
// 动态年龄计算代码
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
 //survivor_capacity是survivor空间的大小
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);//TargetSurvivorRatio 为50
size_t total = 0;
uint age = 1;
while (age < table_size) {
total += sizes[age];//sizes数组是每个年龄段对象大小
if (total > desired_survivor_size) break;
age++;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
  ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6. Di area memori manakah benda berukuran besar ditempatkan?

Jawaban: Objek besar (array dan string yang sangat besar) biasanya dialokasikan langsung di area memori generasi lama.Hal ini untuk mencegah generasi baru sering tampilPengumpulan sampahSaat ini, benda-benda berukuran besar sering tersalin antara kawasan Eden dan kawasan Survivor, sehingga meningkatkan efisiensi pengumpulan sampah.
Konfigurasikan ambang batas objek besar untuk langsung masuk ke generasi lama:

# 将大于1MB的对象直接分配在老年代
java -XX:PretenureSizeThreshold=1m -jar your-application.jar
  • 1
  • 2

7. Bagaimana proses pembuatan objek Java?

menjawab:

  1. Pemeriksaan pemuatan kelas
    • Jika kelas belum dimuat, terhubung dan diinisialisasi, JVM akan memuat kelas tersebut terlebih dahulu. Ini mencakup langkah-langkah berikut:
      • Memuat: Membaca file kelas melalui pemuat kelas dan memuat bytecode kelas ke dalam memori.
      • Koneksi: mencakup tiga tahap: verifikasi, persiapan, dan penguraian. Verifikasi kebenaran file kelas, siapkan variabel statis kelas dan alokasi memori, dan selesaikan referensi simbol menjadi referensi langsung.
      • Inisialisasi: Jalankan blok inisialisasi statis kelas dan inisialisasi variabel statis.
  2. alokasi memori
    • JVM mengalokasikan memori untuk objek baru di heap. Ukuran memori yang dialokasikan ditentukan oleh struktur objek, termasuk header objek dan data instance.
    • JVM memiliki dua cara utama mengalokasikan memori:
      • Bump-the-pointer: Jika memori heap teratur, penunjuk alokasi hanya perlu berpindah jarak tertentu ke area memori bebas.
      • Daftar Gratis: Jika memori heap tidak teratur, JVM perlu mempertahankan daftar bebas dan menemukan blok yang sesuai dari daftar bebas saat mengalokasikan memori.
  3. inisialisasi ke nilai nol
    • JVM akan menginisialisasi semua variabel instan objek ke nilai defaultnya. Misalnya, variabel tipe numerik akan diinisialisasi ke 0, variabel tipe Boolean ke false, dan variabel tipe referensi ke null.
  4. Tetapkan tajuk objek
    • Tetapkan informasi header objek di ruang memori objek, yang mencakup kode hash objek, usia pembuatan GC, tanda status kunci, kunci yang dipegang oleh thread, ID thread yang bias, dll.
  5. Inisialisasi konstruktor
    • Panggil konstruktor objek untuk menyelesaikan inisialisasi objek. Ini termasuk melakukan operasi inisialisasi eksplisit pada variabel instan serta kode di badan konstruktor. Langkah-langkah spesifiknya adalah sebagai berikut:
      • Jalankan blok inisialisasi instance kelas.
      • Jalankan metode konstruktor kelas induk dari atas ke bawah sesuai dengan hierarki warisan.
      • Inisialisasi variabel instan ke nilai yang ditentukan secara eksplisit.
      • Jalankan bagian utama dari metode konstruktor kelas.
/**
 * 创建对象的示例代码
 */
public class MyClass {
    private int value;

    public MyClass(int value) {
        this.value = value;
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass(10);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • Proses eksekusi contoh kode di atas adalah sebagai berikut:
    • Pemuatan kelas: JVM memeriksa apakah MyClass telah dimuat. Jika tidak dimuat, kelas MyClass dimuat.
    • Alokasi memori: Alokasikan memori di heap untuk instance baru MyClass.
    • Inisialisasi memori: Inisialisasi memori yang dialokasikan ke nilai default.
    • Setel header objek: Setel metadata di header objek.
    • Inisialisasi konstruktor: Jalankan konstruktor MyClass dan inisialisasi nilai variabel instan menjadi 10.

Referensi