alokasi statis di java - heap, stack, dan generasi permanen


117

Akhir-akhir ini saya banyak membaca tentang skema alokasi memori di java, dan ada banyak keraguan karena saya telah membaca dari berbagai sumber. Saya telah mengumpulkan konsep saya, dan saya akan meminta untuk membahas semua poin dan mengomentarinya. Saya mengetahui bahwa alokasi memori adalah khusus JVM, jadi saya harus mengatakan sebelumnya, bahwa pertanyaan saya adalah khusus Sun.

  1. Kelas (dimuat oleh pemuat kelas) masuk ke area khusus di heap: Generasi Permanen
  2. Semua informasi yang terkait dengan kelas seperti nama kelas, array Objek yang terkait dengan kelas, objek internal yang digunakan oleh JVM (seperti java / lang / Object) dan informasi pengoptimalan masuk ke area Generasi Permanen.
  3. Semua variabel anggota statis disimpan di area Generasi Permanen lagi.
  4. Objek berada di tumpukan yang berbeda: Generasi muda
  5. Hanya ada satu salinan dari setiap metode per kelas, baik metode statis maupun non-statis. Salinan itu diletakkan di area Generasi Permanen. Untuk metode non-statis, semua parameter dan variabel lokal masuk ke tumpukan - dan setiap kali ada pemanggilan konkret dari metode itu, kami mendapatkan kerangka tumpukan baru yang terkait dengannya. Saya tidak yakin di mana variabel lokal dari metode statis disimpan. Apakah mereka berada di tumpukan Generasi Permanen? Atau hanya referensi mereka yang disimpan di area Generasi Permanen, dan salinan sebenarnya ada di tempat lain (Di mana?)
  6. Saya juga tidak yakin di mana jenis kembalian suatu metode disimpan.
  7. Jika objek (di generasi muda) perlu menggunakan anggota statis (di generasi permanen), mereka diberi referensi ke anggota statis && mereka diberi ruang memori yang cukup untuk menyimpan jenis metode yang dikembalikan, dll.

Terima kasih telah melalui ini!

Jawaban:


152

Pertama, seperti yang seharusnya sudah jelas bagi Anda sekarang bahwa hanya ada sedikit orang yang dapat mengkonfirmasi jawaban ini dari pengetahuan tangan pertama. Sangat sedikit orang yang telah mengerjakan JVM HotSpot baru-baru ini atau mempelajarinya secara mendalam untuk benar-benar mengetahuinya. Kebanyakan orang di sini (termasuk saya sendiri) menjawab berdasarkan hal-hal yang mereka lihat ditulis di tempat lain, atau apa yang mereka simpulkan. Biasanya apa yang tertulis di sini, atau di berbagai artikel dan halaman web, didasarkan pada sumber lain yang mungkin atau mungkin tidak pasti. Seringkali ini disederhanakan, tidak akurat atau salah.

Jika Anda menginginkan konfirmasi pasti dari jawaban Anda, Anda benar-benar perlu mengunduh kode sumber OpenJDK ... dan melakukan penelitian Anda sendiri dengan membaca dan memahami kode sumber. Mengajukan pertanyaan tentang SO, atau menelusuri artikel web secara acak bukanlah teknik penelitian akademis yang baik.

Karena itu ...

... pertanyaan saya adalah spesifik Sun.

Pada saat pertanyaan ini diajukan, Sun Microsystems sudah tidak ada lagi. Karena itu, pertanyaannya spesifik untuk Oracle. AFAIK, semua implementasi JVM pihak ketiga saat ini (non-riset) adalah port langsung dari rilis OpenJDK atau diturunkan dari rilis Sun / Oracle lainnya.

Jawaban di bawah ini berlaku untuk rilis Oracle Hotspot dan OpenJDK, dan mungkin juga untuk sebagian besar lainnya ... termasuk GraalVM.

1) Kelas (dimuat oleh pemuat kelas) masuk ke area khusus di heap: Generasi Permanen.

Sebelum ke Java 8, ya.

Mulai Java 8, ruang PermGen telah diganti dengan Metaspace. Kelas yang dimuat dan dikompilasi JIT sekarang berada di sana. PermGen tidak ada lagi.

2) Semua informasi yang terkait dengan kelas seperti nama kelas, array Objek yang terkait dengan kelas, objek internal yang digunakan oleh JVM (seperti java / lang / Object) dan informasi pengoptimalan masuk ke area Generasi Permanen.

Kurang lebih ya. Saya tidak yakin apa yang Anda maksud dengan beberapa hal itu. Saya menduga bahwa "objek internal yang digunakan oleh JVM (seperti java / lang / Object)" berarti deskriptor kelas internal JVM.

3) Semua variabel anggota statis disimpan di area Generasi Permanen lagi.

Variabelnya sendiri ya. Variabel ini (seperti semua variabel Java) akan menyimpan nilai primitif atau referensi objek. Namun, sementara variabel anggota statis berada dalam bingkai yang dialokasikan di tumpukan permgen, objek / larik yang dirujuk oleh variabel tersebut dapat dialokasikan di tumpukan apa pun .

4) Objek berada di tumpukan yang berbeda: Generasi muda

Belum tentu. Objek besar dapat dialokasikan langsung ke generasi bertenor.

5) Hanya ada satu salinan dari setiap metode per kelas, baik metode statis atau non-statis. Salinan itu diletakkan di area Generasi Permanen.

Dengan asumsi Anda mengacu pada kode metode, maka AFAIK ya. Ini mungkin sedikit lebih rumit. Misalnya kode itu mungkin ada dalam bytecode dan / atau bentuk kode asli pada waktu yang berbeda selama masa pakai JVM.

... Untuk metode non-statis, semua parameter dan variabel lokal masuk ke tumpukan - dan setiap kali ada pemanggilan konkret dari metode itu, kami mendapatkan kerangka tumpukan baru yang terkait dengannya.

Iya.

... Saya tidak yakin di mana variabel lokal dari metode statis disimpan. Apakah mereka berada di tumpukan Generasi Permanen? Atau hanya referensi mereka yang disimpan di area Generasi Permanen, dan salinan sebenarnya ada di tempat lain (Di mana?)

Tidak. Mereka disimpan di tumpukan, seperti variabel lokal dalam metode non-statis.

6) Saya juga tidak yakin di mana jenis kembalian suatu metode disimpan.

Jika yang Anda maksud adalah nilai yang dikembalikan oleh panggilan metode (non-void), maka nilai tersebut dikembalikan pada stack atau dalam register mesin. Jika dikembalikan pada tumpukan, ini membutuhkan 1 atau dua kata, tergantung pada jenis pengembalian.

7) Jika objek (di generasi muda) perlu menggunakan anggota statis (di generasi permanen), mereka diberi referensi ke anggota statis && mereka diberi ruang memori yang cukup untuk menyimpan jenis kembalian metode, dll. .

Itu tidak akurat (atau setidaknya, Anda tidak mengekspresikan diri Anda dengan jelas).

Jika beberapa metode mengakses variabel anggota statis, yang didapatnya adalah nilai primitif atau referensi objek . Ini dapat ditugaskan ke variabel atau parameter lokal (yang ada), ditugaskan ke anggota statis atau non-statis (yang ada), ditugaskan ke elemen (yang ada) dari larik yang dialokasikan sebelumnya, atau hanya digunakan dan dibuang.

  • Dalam hal apa pun penyimpanan baru tidak perlu dialokasikan untuk menampung referensi atau nilai primitif.

  • Biasanya, hanya satu kata memori yang diperlukan untuk menyimpan referensi objek atau larik, dan nilai primitif biasanya menempati satu atau dua kata, tergantung pada arsitektur perangkat keras.

  • Dalam kasus apa pun tidak ada ruang yang perlu dialokasikan oleh pemanggil untuk menampung beberapa objek / larik yang dikembalikan oleh suatu metode. Di Java, objek dan array selalu dikembalikan menggunakan semantik pass-by-value ... tetapi nilai yang dikembalikan adalah referensi objek atau array.


Untuk informasi lebih lanjut, silakan merujuk ke sumber daya ini:

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.