Seperti yang saya mengerti, di Jawa, memori stack menampung primitif dan metode doa dan memori tumpukan digunakan untuk menyimpan objek.
Misalkan saya punya kelas
class A {
int a ;
String b;
//getters and setters
}
Di mana primitif
a
di kelasA
akan disimpan?Mengapa tumpukan memori ada sama sekali? Mengapa kita tidak bisa menyimpan semuanya di stack?
Ketika objek dikumpulkan, apakah tumpukan yang terkait dengan keberatan dihancurkan?
Jawaban:
Perbedaan mendasar antara tumpukan dan tumpukan adalah siklus hidup dari nilai-nilai.
Nilai tumpukan hanya ada dalam lingkup fungsi tempat mereka dibuat. Setelah kembali, nilai tersebut dibuang.
Namun nilai heap ada di heap. Mereka dibuat di beberapa titik waktu, dan dirusak di tempat lain (baik oleh GC atau secara manual, tergantung pada bahasa / runtime).
Sekarang Java hanya menyimpan primitif di stack. Ini menjaga stack tetap kecil dan membantu menjaga frame stack individual tetap kecil, sehingga memungkinkan lebih banyak panggilan bersarang.
Objek dibuat di heap, dan hanya referensi (yang pada gilirannya adalah primitif) dilewatkan di tumpukan.
Jadi jika Anda membuat objek, ia diletakkan di heap, dengan semua variabel yang menjadi miliknya, sehingga bisa bertahan setelah fungsi panggil kembali.
sumber
char
s adalah angka dan dapat digunakan secara bergantian. Referensi juga hanya nomor yang merujuk ke alamat memori, panjangnya 32 atau 64 bit (meskipun tidak dapat digunakan seperti itu - kecuali jika Anda mengacaukannyasun.misc.Unsafe
).boolean
,byte
,short
,char
,int
,long
,float
Dandouble
.)Di mana bidang primitif disimpan?
Bidang primitif disimpan sebagai bagian dari objek yang dipakai di suatu tempat . Cara termudah untuk memikirkan di mana ini - adalah tumpukan. Namun , ini tidak selalu terjadi. Seperti yang dijelaskan dalam teori dan praktik Java: Legenda kinerja perkotaan, ditinjau kembali :
Jadi, melampaui mengatakan "objek dibuat dan bidang ada di sana juga", orang tidak dapat mengatakan apakah ada sesuatu di tumpukan atau di tumpukan. Perhatikan bahwa untuk objek kecil, berumur pendek, kemungkinan bahwa 'objek' tidak akan ada dalam memori seperti itu dan sebagai gantinya dapat menempatkan bidangnya langsung di register.
Makalah ini diakhiri dengan:
Jadi, jika Anda memiliki kode yang terlihat seperti:
di mana yang
...
tidak memungkinkanqux
untuk meninggalkan ruang lingkup itu,qux
dapat dialokasikan pada tumpukan sebagai gantinya. Ini sebenarnya adalah kemenangan untuk VM karena itu berarti tidak perlu menjadi sampah yang dikumpulkan - itu akan hilang ketika meninggalkan ruang lingkup.Lebih lanjut tentang analisis pelarian di Wikipedia. Bagi mereka yang ingin mempelajari makalah, Escape Analysis for Java dari IBM. Bagi mereka yang berasal dari dunia C #, Anda mungkin menemukan The Stack Is an Detail Implementasi dan The Truth About Value Type oleh Eric Lippert bacaan yang baik (mereka berguna untuk tipe Java juga karena banyak konsep dan aspek yang sama atau mirip) . Mengapa .Net buku berbicara tentang alokasi memori tumpukan vs tumpukan? juga masuk ke ini.
Di mengapa tumpukan dan tumpukan
Di atas tumpukan
Jadi, mengapa memiliki tumpukan atau tumpukan sama sekali? Untuk hal-hal yang meninggalkan ruang lingkup, tumpukan bisa mahal. Pertimbangkan kodenya:
Parameter juga merupakan bagian dari tumpukan. Dalam situasi yang Anda tidak memiliki tumpukan, Anda akan melewati set nilai penuh pada tumpukan. Ini bagus untuk
"foo"
dan string kecil ... tapi apa yang akan terjadi jika seseorang meletakkan file XML besar di string itu. Setiap panggilan akan menyalin seluruh string besar ke tumpukan - dan itu akan sangat sia-sia.Sebaliknya, lebih baik untuk meletakkan benda-benda yang memiliki kehidupan di luar lingkup langsung (diteruskan ke lingkup lain, terjebak dalam struktur yang dipelihara orang lain, dll ...) ke area lain yang disebut tumpukan.
Di tumpukan
Anda tidak perlu tumpukan. Seseorang dapat, secara hipotetis, menulis bahasa yang tidak menggunakan tumpukan (kedalaman arbitrer). BASIC lama yang saya pelajari di masa muda saya melakukannya, seseorang hanya bisa melakukan 8 level
gosub
panggilan dan semua variabel bersifat global - tidak ada tumpukan.Keuntungan dari stack adalah ketika Anda memiliki variabel yang ada dengan cakupan, ketika Anda meninggalkan cakupan itu, frame tumpukan itu muncul. Itu benar-benar menyederhanakan apa yang ada dan apa yang tidak ada. Program pindah ke prosedur lain, bingkai tumpukan baru; program kembali ke prosedur, dan Anda telah kembali ke prosedur yang melihat lingkup Anda saat ini; program meninggalkan prosedur dan semua item pada stack tidak dapat dialokasikan.
Ini benar-benar membuat hidup mudah bagi orang yang menulis runtime untuk kode untuk menggunakan stack dan heap. Mereka hanya banyak konsep dan cara kerja pada kode yang memungkinkan orang yang menulis kode dalam bahasa dibebaskan dari memikirkannya secara eksplisit.
Sifat stack juga berarti tidak bisa terfragmentasi. Fragmentasi memori adalah masalah nyata dengan heap. Anda mengalokasikan beberapa objek, lalu sampah mengumpulkan yang di tengah, dan kemudian mencoba menemukan ruang untuk yang besar berikutnya untuk dialokasikan. Ini berantakan. Mampu meletakkan barang-barang di tumpukan berarti Anda tidak harus berurusan dengan itu.
Ketika sesuatu sampah dikumpulkan
Ketika sesuatu dikumpulkan, sampah itu hilang. Tapi itu hanya sampah yang dikumpulkan karena sudah dilupakan - tidak ada lagi referensi ke objek dalam program yang dapat diakses dari kondisi program saat ini.
Saya akan menunjukkan bahwa ini adalah penyederhanaan pengumpulan sampah yang sangat besar. Ada banyak pengumpul sampah (bahkan di Jawa - Anda dapat men-tweak pengumpul sampah dengan menggunakan berbagai bendera ( docs ). Ini berperilaku berbeda dan nuansa bagaimana masing-masing melakukan hal-hal agak terlalu dalam untuk jawaban ini. Anda mungkin ingin membaca Dasar - Dasar Pengumpulan Sampah Jawa untuk mendapatkan ide yang lebih baik tentang bagaimana beberapa di antaranya berfungsi.
Yang mengatakan, jika sesuatu dialokasikan pada tumpukan, itu bukan sampah yang dikumpulkan sebagai bagian dari
System.gc()
- itu tidak dialokasikan ketika bingkai tumpukan muncul. Jika ada sesuatu di tumpukan, dan direferensikan dari sesuatu di tumpukan, itu tidak akan menjadi sampah yang dikumpulkan saat itu.Mengapa ini penting?
Sebagian besar, tradisi. Buku-buku teks yang ditulis dan kelas kompilasi dan berbagai bit dokumentasi membuat masalah besar tentang tumpukan dan tumpukan.
Namun, mesin virtual saat ini (JVM dan sejenisnya) telah berusaha keras untuk mencoba menyembunyikan ini dari programmer. Kecuali jika Anda kehabisan satu dan yang lain dan perlu tahu mengapa (bukan hanya menambah ruang penyimpanan dengan tepat), itu tidak terlalu menjadi masalah.
Objek berada di suatu tempat dan berada di tempat di mana ia dapat diakses dengan benar dan cepat untuk jumlah waktu yang tepat yang ada. Jika ada di tumpukan atau tumpukan - itu tidak masalah.
sumber
sumber
Pada heap kecuali Java mengalokasikan instance kelas pada stack sebagai optimisasi setelah membuktikan melalui analisis escape bahwa ini tidak akan mempengaruhi semantik. Ini adalah detail implementasi, jadi, untuk semua tujuan praktis kecuali optimasi mikro jawabannya adalah "on the heap".
Stack memory harus dialokasikan dan dideallocate pada urutan terakhir dengan urutan pertama. Memori tumpukan dapat dialokasikan dan dialokasikan dengan cara apa pun.
Ketika objek sampah dikumpulkan, tidak ada referensi lagi yang menunjuknya dari tumpukan. Jika ada, mereka akan menjaga objek tetap hidup. Primitif tumpukan bukan sampah yang dikumpulkan sama sekali karena mereka secara otomatis dihancurkan ketika fungsi kembali.
sumber
Memori tumpukan digunakan untuk menyimpan variabel lokal dan panggilan fungsi.
Sedangkan heap memory digunakan untuk menyimpan objek di Jawa. Tidak masalah, di mana objek dibuat dalam kode.
Dalam hal ini primitif a dikaitkan dengan objek kelas A. Jadi itu menciptakan Heap Memory.
Garbage Collector bekerja di bawah ruang lingkup memori Heap, sehingga menghancurkan objek yang tidak memiliki rantai referensi dari ke root.
sumber
Untuk pemahaman yang lebih baik (Heap / Stack memory):
sumber