Saya tahu konsep kumpulan konstanta dan kumpulan konstanta String yang digunakan oleh JVM untuk menangani literal String. Tapi saya tidak tahu jenis memori yang digunakan oleh JVM untuk menyimpan literal konstan String. Tumpukan atau tumpukan? Karena ini literal yang tidak terkait dengan contoh apa pun, saya akan berasumsi bahwa itu akan disimpan dalam tumpukan. Tetapi jika tidak dirujuk oleh contoh apa pun, literal harus dikumpulkan oleh GC run (perbaiki saya jika saya salah), jadi bagaimana penanganannya jika disimpan dalam tumpukan?
104
Jawaban:
Jawabannya secara teknis tidak keduanya. Menurut Spesifikasi Mesin Virtual Java, area untuk menyimpan literal string berada dalam kumpulan konstan runtime . Area memori kumpulan konstan waktu proses dialokasikan pada basis per kelas atau per antarmuka, jadi tidak terikat ke instance objek sama sekali. Kumpulan konstan runtime adalah bagian dari area metode yang "menyimpan struktur per kelas seperti kumpulan konstan runtime, data bidang dan metode, dan kode untuk metode dan konstruktor, termasuk metode khusus yang digunakan di kelas dan inisialisasi instance dan antarmuka. ketik inisialisasi ". Spesifikasi VM mengatakan bahwa meskipun area metode secara logis adalah bagian dari heap, itu tidak menentukan bahwa memori yang dialokasikan di area metode tunduk pada pengumpulan sampah atau perilaku lain yang akan dikaitkan dengan struktur data normal yang dialokasikan ke heap.
sumber
Seperti yang dijelaskan oleh jawaban ini , lokasi pasti dari kumpulan string tidak ditentukan dan dapat bervariasi dari satu implementasi JVM ke implementasi JVM lainnya.
Menarik untuk diperhatikan bahwa hingga Java 7, kumpulan tersebut berada di ruang permgen dari heap di hotspot JVM tetapi telah dipindahkan ke bagian utama dari heap sejak Java 7 :
Dan di Java 8 Hotspot, Permanent Generation telah dihapus seluruhnya.
sumber
Literal string tidak disimpan di tumpukan. Tidak pernah. Faktanya, tidak ada objek yang disimpan di tumpukan.
Literal string (atau lebih tepatnya, objek String yang mewakilinya)
secarahistoris disimpan dalam Heap yang disebut heap "permgen". (Permgen adalah kependekan dari generasi permanen.)Dalam keadaan normal, literal String dan banyak hal lainnya di heap permgen dapat dijangkau "secara permanen", dan tidak dikumpulkan dari sampah. (Misalnya, string literal selalu dapat dijangkau dari objek kode yang menggunakannya.) Namun, Anda dapat mengonfigurasi JVM untuk mencoba menemukan dan mengumpulkan kelas yang dimuat secara dinamis yang tidak lagi diperlukan, dan ini dapat menyebabkan literal String menjadi sampah yang dikumpulkan .
KLARIFIKASI # 1 - Saya tidak mengatakan bahwa Permgen tidak mendapatkan GC'ed. Ya, biasanya ketika JVM memutuskan untuk menjalankan GC Penuh. Maksud saya adalah bahwa string literal akan dapat dijangkau selama kode yang menggunakannya dapat dijangkau, dan kode akan dapat dijangkau selama classloader kode tersebut dapat dijangkau, dan untuk classloader default, itu berarti "selamanya".
KLARIFIKASI # 2 - Faktanya, Java 7 dan yang lebih baru menggunakan heap biasa untuk menampung kumpulan string. Jadi, objek String yang mewakili literal String dan string internal sebenarnya berada di heap reguler. (Lihat Jawaban @ assylias untuk detailnya.)
Tidak ada "garis tipis". Ini sangat sederhana:
String
objek yang mewakili / sesuai dengan literal string disimpan di kumpulan string.String
objek yang dibuat olehString::intern
panggilan ditahan di kumpulan string.String
objek lain TIDAK diadakan di kumpulan string.Lalu ada pertanyaan terpisah di mana kumpulan string "disimpan". Sebelum Java 7 itu adalah permgen heap. Dari Java 7 dan seterusnya, ini adalah heap utama.
sumber
Penggabungan string
String.intern () di Java 6
String.intern () di Java 7
Nilai kumpulan string adalah sampah yang dikumpulkan
sumber.
sumber
Seperti jawaban lain menjelaskan Memori di Java dibagi menjadi dua bagian
1. Tumpukan: Satu tumpukan dibuat per utas dan ia menyimpan bingkai tumpukan yang lagi-lagi menyimpan variabel lokal dan jika variabel adalah tipe referensi, maka variabel tersebut merujuk ke lokasi memori di tumpukan untuk objek sebenarnya.
2. Heap: Semua jenis objek hanya akan dibuat di heap.
Memori heap sekali lagi dibagi menjadi 3 bagian
1. Generasi Muda: Menyimpan benda-benda yang memiliki umur pendek, Generasi Muda sendiri dapat dibagi menjadi dua kategori Eden Space dan Survivor Space .
2. Generasi Lama: Menyimpan objek yang selamat dari banyak siklus pengumpulan sampah dan masih menjadi referensi.
3. Generasi Permanen: Menyimpan metadata tentang program misalnya kumpulan konstan runtime.
Kumpulan konstan string milik area generasi permanen memori Heap.
Kita dapat melihat kumpulan konstan runtime untuk kode kita di bytecode dengan menggunakan
javap -verbose class_name
yang akan menunjukkan kepada kita referensi metode (#Methodref), Objek kelas (#Class), string literals (#String)Anda dapat membaca lebih lanjut tentang itu di artikel saya Bagaimana JVM Menangani Metode Overloading dan Overriding Secara Internal .
sumber
Untuk jawaban-jawaban hebat yang sudah disertakan di sini, saya ingin menambahkan sesuatu yang hilang dalam perspektif saya - sebuah ilustrasi.
Karena Anda sudah, JVM membagi memori yang dialokasikan ke program Java menjadi dua bagian. satu tumpukan dan satu lagi tumpukan . Stack digunakan untuk tujuan eksekusi dan heap digunakan untuk tujuan penyimpanan. Dalam memori heap tersebut, JVM mengalokasikan beberapa memori yang secara khusus dimaksudkan untuk string literal. Bagian dari memori heap ini disebut kumpulan konstanta string .
Jadi misalnya, jika Anda melakukan init objek berikut:
String literal
s1
dans2
akan pergi ke kumpulan konstan string, objek obj1, obj2, obj3 ke heap. Semuanya, akan direferensikan dari Stack.Juga, harap dicatat bahwa "abc" akan muncul di heap dan di kumpulan konstan string. Mengapa
String s1 = "abc"
danString obj1 = new String("abc")
akan diciptakan dengan cara ini? Itu karenaString obj1 = new String("abc")
secara eksplisit membuat instance baru dan berbeda secara referensial dari objek String danString s1 = "abc"
dapat menggunakan kembali instance dari kumpulan konstan string jika tersedia. Untuk penjelasan yang lebih terperinci: https://stackoverflow.com/a/3298542/2811258sumber