Alokasi dan manajemen memori Java adalah salah satu teknologi inti Java. Kami sebelumnya telah memperkenalkan pengetahuan tentang manajemen memori Java, kebocoran memori dan koleksi sampah Java. Hari ini, kita akan sekali lagi masuk ke dalam inti Java dan memperkenalkan secara rinci pengetahuan Java dalam alokasi memori. Secara umum, Java akan melibatkan area berikut saat mengalokasikan memori:
◆ Daftar: Kami tidak dapat mengontrolnya dalam program
◆ Tumpukan: Menyimpan jenis data dasar dan referensi ke objek, tetapi objek itu sendiri tidak disimpan dalam tumpukan, tetapi disimpan dalam tumpukan (objek yang keluar dari yang baru)
◆ Heap: Simpan data yang dihasilkan menggunakan baru
◆ Domain statis: Anggota statis disimpan dalam objek yang ditentukan dengan statis
◆ Kolam renang konstan: Simpan konstanta
◆ Penyimpanan Non-RAM: Ruang penyimpanan permanen seperti hard disk
Tumpukan dalam Alokasi Memori Java
Beberapa tipe dasar data variabel yang ditentukan dalam fungsi dan variabel referensi objek semuanya dialokasikan dalam memori tumpukan fungsi.
Ketika suatu variabel didefinisikan dalam blok kode, Java mengalokasikan ruang memori untuk variabel dalam tumpukan. Ketika variabel keluar dari ruang lingkup, Java akan secara otomatis melepaskan ruang memori yang dialokasikan untuk variabel, dan ruang memori dapat digunakan secara terpisah segera. Ukuran data dan siklus hidup dalam tumpukan sudah pasti, dan data ini menghilang ketika tidak ada referensi yang menunjuk ke data.
Tumpukan dalam alokasi memori Java
Heap Memory digunakan untuk menyimpan objek dan array yang dibuat oleh baru. Memori yang dialokasikan dalam tumpukan dikelola oleh pengumpul sampah otomatis mesin virtual Java.
Setelah array atau objek dihasilkan dalam heap, variabel khusus dapat didefinisikan dalam tumpukan, sehingga nilai variabel ini dalam tumpukan sama dengan alamat pertama array atau objek dalam memori heap, dan variabel dalam tumpukan menjadi variabel referensi untuk array atau objek. Variabel referensi setara dengan nama yang diberikan ke array atau objek. Anda dapat menggunakan variabel referensi di tumpukan dalam program untuk mengakses array atau objek di heap. Variabel referensi setara dengan nama yang diberikan ke array atau objek.
Variabel referensi adalah variabel biasa, yang ditetapkan pada tumpukan saat didefinisikan. Variabel referensi dirilis setelah program berjalan di luar ruang lingkupnya. Array dan objek itu sendiri dialokasikan di tumpukan. Bahkan jika program berjalan di luar blok kode di mana pernyataan yang menggunakan baru untuk menghasilkan array atau objek berada, memori yang ditempati oleh array dan objek itu sendiri tidak akan dilepaskan. Array dan objek hanya menjadi sampah ketika tidak ada variabel referensi yang menunjuk ke sana, dan tidak dapat digunakan, tetapi masih menempati ruang memori. Ini dikumpulkan (dilepaskan) oleh pengumpul sampah pada waktu yang tidak pasti. Ini juga alasan mengapa Java mengambil lebih banyak memori.
Bahkan, variabel dalam titik tumpukan ke variabel dalam memori heap, yang merupakan pointer di java!
Tumpukan dan Tumpukan
Tumpukan Java adalah area data runtime, dari mana objek mengalokasikan ruang. Objek -objek ini dibuat melalui instruksi seperti New, NewArray, Anewarray dan Multianewarray. Mereka tidak memerlukan kode program untuk dirilis secara eksplisit. Tumpukan bertanggung jawab untuk pengumpulan sampah. Keuntungan dari tumpukan adalah bahwa ia dapat secara dinamis mengalokasikan ukuran memori dan tidak harus memberi tahu kompiler terlebih dahulu karena secara dinamis mengalokasikan memori saat runtime. Pengumpul sampah Java akan secara otomatis mengumpulkan data yang tidak lagi digunakan. Tetapi kerugiannya adalah karena perlu mengalokasikan memori secara dinamis saat runtime, kecepatan akses lebih lambat.
Keuntungan dari tumpukan adalah bahwa kecepatan akses lebih cepat dari tumpukan, kedua setelah register, dan data tumpukan dapat dibagikan. Tetapi kerugiannya adalah bahwa ukuran data dan masa pakai dalam tumpukan harus deterministik dan tidak memiliki fleksibilitas. Tumpukan terutama menyimpan beberapa jenis dasar data variabel (int, pendek, panjang, byte, float, double, boolean, char) dan pegangan objek (referensi).
Fitur khusus yang sangat penting dari tumpukan adalah bahwa data yang ada di tumpukan dapat dibagikan. Misalkan kita mendefinisikan pada saat yang sama:
Kode Java
int a = 3;
int b = 3;
Kompiler pertama proses int a = 3; Pertama akan membuat referensi di tumpukan dengan variabel A, dan kemudian cari tahu apakah ada nilai 3 di tumpukan. Jika tidak ditemukan, itu akan menyimpan 3 dan kemudian titik A ke 3. Kemudian proses int b = 3; Setelah membuat variabel referensi B, karena sudah ada nilai 3 di tumpukan, B secara langsung menunjuk ke 3. Dengan cara ini, A dan B keduanya menunjuk ke 3 pada saat yang sama.
Pada saat ini, jika a = 4 diatur lagi; maka kompiler akan mencari lagi apakah ada nilai 4 di tumpukan. Jika tidak, simpan 4 dan point A ke 4; Jika sudah ada, poin A ke alamat ini secara langsung. Oleh karena itu, perubahan nilai A tidak akan mempengaruhi nilai b.
Perlu dicatat bahwa berbagi data ini berbeda dari berbagi referensi dari dua objek yang menunjuk ke satu objek pada saat yang sama, karena dalam hal ini modifikasi A tidak akan mempengaruhi B, itu dilakukan oleh kompiler, yang kondusif untuk menghemat ruang. Variabel referensi objek memodifikasi keadaan internal objek ini dan akan memengaruhi variabel referensi objek lain.
Kode Java
1.int I1 = 9;
2.int I2 = 9;
3.int i3 = 9;
4.Public static final int int1 = 9;
5. Public static final int int2 = 9;
6. Public static final int int3 = 9;
Untuk variabel anggota dan variabel lokal: variabel anggota adalah variabel yang didefinisikan di dalam metode dan kelas; Variabel lokal adalah variabel yang didefinisikan di dalam metode atau blok pernyataan. Variabel lokal harus diinisialisasi.
Parameter formal adalah variabel lokal, dan data variabel lokal ada dalam memori tumpukan. Variabel lokal dalam memori tumpukan menghilang saat metode menghilang.
Variabel anggota disimpan dalam objek di tumpukan dan dikumpulkan oleh pengumpul sampah.
Seperti dalam kode berikut:
Kode Java
Class BirthDate {private int day; Bulan int pribadi; tahun int pribadi; kelahiran publik (int d, int m, int y) {day = d; bulan = m; tahun = y; } oMit get, atur metode ……} tes kelas publik {public static void main (string args []) {int date = 9; Tes tes = tes baru (); test.change (tanggal); BirthDate D1 = Tanggal lahir baru (7,7,1970); } public void change1 (int i) {i = 1234; }Untuk kode di atas, tanggal adalah variabel lokal, i, d, m, y adalah semua parameter formal sebagai variabel lokal, dan hari, bulan, dan tahun adalah variabel anggota. Mari kita analisis perubahan selama eksekusi kode:
1. Metode utama mulai mengeksekusi: Tanggal int = 9;
Tanggal variabel lokal, tipe dasar, referensi dan nilai semuanya ada di tumpukan.
2. Uji tes = tes baru ();
Tes adalah referensi objek, ada pada tumpukan, dan objek (tes baru ()) ada pada tumpukan.
3. test.change (tanggal);
Saya adalah variabel lokal, dan referensi dan nilainya ada di tumpukan. Ketika perubahan metode dieksekusi, saya akan menghilang dari tumpukan.
4. BirthDate D1 = Tanggal lahir baru (7,7,1970);
D1 adalah referensi objek dan ada di tumpukan. Objek (BirthDate baru ()) ada di tumpukan, di mana d, m, y adalah variabel lokal yang disimpan dalam tumpukan, dan jenisnya adalah jenis dasar, sehingga data mereka juga disimpan dalam tumpukan. Hari, bulan, tahun adalah variabel anggota, dan mereka disimpan di tumpukan (BirthDate baru ()). Ketika konstruktor Tanggal lahir dieksekusi, D, M, y akan hilang dari tumpukan.
5. Setelah metode utama dieksekusi, variabel tanggal, tes, dan referensi D1 akan hilang dari tumpukan, dan tes baru (), BirthDate baru () akan menunggu pengumpulan sampah.
Kolam konstan
Kumpulan konstan mengacu pada beberapa data yang ditentukan selama periode kompilasi dan disimpan dalam file .class yang dikompilasi.
Selain mengandung nilai konstan (final) dari berbagai tipe dasar (seperti int, long, dll.) Dan tipe objek (seperti string dan array) yang ditentukan dalam kode, itu juga berisi beberapa referensi simbolik dalam bentuk teks, seperti: seperti:
◆ Nama kelas dan antarmuka yang memenuhi syarat;
◆ Nama dan deskriptor lapangan;
◆ Metode dan nama dan deskriptor.
Jika periode kompilasi telah dibuat (didefinisikan secara langsung dalam kutipan ganda), itu akan disimpan di kumpulan konstan, dan jika dapat ditentukan oleh periode berjalan (dari yang baru), itu akan disimpan dalam tumpukan. Untuk string dengan setara, selalu ada satu salinan di kumpulan konstan dan beberapa salinan di heap.
String adalah data pengemasan khusus. Dapat digunakan:
Kode Java
String str = string baru ("abc"); string str = "abc";Ada dua bentuk untuk dibuat. Yang pertama adalah menggunakan baru () untuk membuat objek baru, yang akan disimpan di tumpukan. Objek baru dibuat setiap kali dipanggil. Tipe kedua adalah untuk pertama -tama membuat variabel STR ke objek kelas string di tumpukan, dan kemudian menggunakan referensi simbolik untuk mengetahui apakah ada "ABC" di kumpulan string konstan. Jika tidak, simpan "ABC" ke dalam kolam konstanta tali dan biarkan STR ke "ABC". Jika sudah ada "ABC", maka langsung biarkan STR ke "ABC".
Saat membandingkan apakah nilai -nilai di kelas sama, gunakan metode Equals (); Saat menguji apakah referensi dari dua kelas pembungkus menunjuk ke objek yang sama, gunakan ==, dan gunakan contoh di bawah ini untuk menggambarkan teori di atas.
Kode Java
String str1 = "abc"; string str2 = "abc"; System.out.println (str1 == str2); //BENAR
Dapat dilihat bahwa STR1 dan STR2 menunjuk ke objek yang sama.
Kode Java
String str1 = string baru ("abc"); string str2 = string baru ("abc"); system.out.println (str1 == str2); // PALSUMetode baru adalah menghasilkan objek yang berbeda. Menghasilkan satu per satu.
Oleh karena itu, dengan cara kedua, beberapa string "ABC" dibuat, dan hanya ada satu objek dalam memori. Metode penulisan ini bermanfaat dan menghemat ruang memori. Pada saat yang sama, dapat meningkatkan kecepatan berjalan program sampai batas tertentu, karena JVM akan secara otomatis memutuskan apakah perlu membuat objek baru berdasarkan situasi aktual data dalam tumpukan. Untuk kode string str = string baru ("ABC");, objek baru dibuat dalam tumpukan terlepas dari apakah nilai string mereka sama atau tidak, apakah perlu membuat objek baru, sehingga meningkatkan beban pada program.
Di sisi lain, perhatikan: ketika kami mendefinisikan kelas menggunakan format seperti string str = "ABC";, kami selalu menerima begitu saja bahwa kami membuat objek STR dari kelas string. Khawatir tentang jebakan! Objek mungkin belum dibuat! Dan mungkin hanya menunjuk ke objek yang telah dibuat sebelumnya. Hanya melalui metode baru () kita dapat memastikan bahwa objek baru dibuat setiap saat.
Beberapa contoh masalah pengumpulan konstan string
Contoh 1:
Kode Java
String s0 = "kvill"; string s1 = "kvill"; string s2 = "kv" + "sakit"; System.out.println (s0 == s1); System.out.println (s0 == S2); Hasilnya adalah: Truetrue
Analisis: Pertama -tama, kita perlu tahu bahwa hasilnya adalah Java akan memastikan bahwa konstanta string hanya memiliki satu salinan.
Karena S0 dan S1 dalam contoh adalah konstanta string, mereka ditentukan selama periode kompilasi, jadi S0 == S1 benar; dan "kv" dan "sakit" juga merupakan konstanta string. Ketika string dihubungkan oleh beberapa konstanta string, itu jelas merupakan konstanta string itu sendiri, jadi S2 juga diuraikan menjadi konstanta string selama periode kompilasi, jadi S2 juga merupakan referensi untuk "kvill" di kumpulan konstan. Jadi kita mendapatkan S0 == S1 == S2;
Contoh 2:
Contoh:
Kode Java
Analisis: String yang dibuat dengan string baru () bukan konstanta dan tidak dapat ditentukan selama periode kompilasi, sehingga string yang dibuat oleh string baru () tidak ditempatkan di kumpulan konstan, mereka memiliki ruang alamat sendiri.
S0 juga merupakan aplikasi "kvill" di kolam konstan. S1 tidak dapat ditentukan selama periode kompilasi, jadi ini merupakan referensi ke objek baru "KVill" yang dibuat saat runtime. S2 tidak dapat ditentukan selama periode kompilasi karena memiliki paruh kedua dari string baru ("sakit"), jadi itu juga merupakan aplikasi dari objek yang baru dibuat "kvill"; Jika Anda memahami ini, Anda akan tahu mengapa hasil ini diperoleh.
Contoh 3:
Kode Java
String a = "a1"; string b = "a" + 1; system.out.println ((a == b)); // hasil = string true a = "true"; string b = "a" + "true"; System.out.println ((a == b)); // hasil = string true a = "a3.4"; string b = "a" + 3.4; System.out.println ((a == b)); // hasil = true
Analisis: Untuk koneksi JVM dari konstanta string, JVM mengoptimalkan koneksi "+" dari string konstan ke nilai yang terhubung setelah periode kompilasi program. Ambil "A" + 1 sebagai contoh. Setelah optimasi oleh kompiler, sudah A1 di kelas. Selama periode kompilasi, nilai konstanta string ditentukan, sehingga hasil akhir dari program di atas benar.
Contoh 4:
Kode Java
String a = "ab"; string bb = "b"; string b = "a" + bb; system.out.println ((a == b)); // hasil = false
Analisis: Untuk referensi string dalam JVM, karena ada referensi string dalam koneksi " +" string, nilai yang direferensikan tidak dapat ditentukan selama periode kompilasi program, yaitu, "A" + BB tidak dapat dioptimalkan oleh kompiler, dan hanya mengalokasikan secara dinamis dan memberikan alamat baru yang terhubung ke B selama periode menjalankan program. Oleh karena itu, hasil dari program di atas salah.
Contoh 5:
Kode Java
String a = "ab"; string final bb = "b"; string b = "a" + bb; system.out.println ((a == b)); // hasil = true
Analisis: Satu -satunya perbedaan antara [4] adalah bahwa string BB dihiasi dengan modifikasi akhir. Untuk variabel final yang dimodifikasi, ini diuraikan sebagai salinan lokal dari nilai konstan pada waktu kompilasi dan disimpan dalam kumpulan konstannya sendiri atau tertanam dalam aliran bytecode. Jadi pada saat ini efek "A" + BB dan "A" + "B" adalah sama. Oleh karena itu, hasil dari program di atas adalah benar.
Contoh 6:
Kode Java
String a = "ab"; string akhir bb = getBb (); string b = "a" + bb; System.out.println ((a == b)); // result = falseprivate string statis getBb () {return "b"; }Analisis: Referensi JVM BB untuk string, dan nilainya tidak dapat ditentukan selama periode kompilasi. Hanya setelah memanggil metode selama runtime program, nilai pengembalian metode dan "A" terhubung secara dinamis dan alamatnya ditugaskan ke B. Oleh karena itu, hasil dari program di atas salah.
Tentang string tidak dapat diubah
Dari contoh di atas, kita dapat mencari tahu:
String s = "a" + "b" + "c";
Itu setara dengan string S = "ABC";
String a = "a";
String b = "b";
String c = "c";
String S = A + B + C;
Ini berbeda, hasil akhirnya sama dengan:
Kode Java
StringBuffer Temp = New StringBuffer (); Temp.Append (a) .Append (B) .Append (C); String S = Temp.ToString ();
Dari hasil analisis di atas, tidak sulit untuk menyimpulkan bahwa string menggunakan operator koneksi (+) untuk menganalisis alasan inefisiensi, seperti kode ini:
Kode Java
tes kelas publik {public static void main (string args []) {string s = null; untuk (int i = 0; i <100; i ++) {s+= "a"; }}}Setiap kali + selesai, objek StringBuilder dihasilkan, dan kemudian menambahkannya dan membuangnya. Lain kali loop tiba, objek StringBuilder diregenerasi, dan kemudian menambahkan string, dan loop selesai sampai berakhir. Jika kita secara langsung menggunakan objek StringBuilder untuk ditambahkan, kita dapat menghemat waktu untuk membuat dan menghancurkan objek. Oleh karena itu, untuk aplikasi yang memerlukan gabungan string dalam loop, operasi append umumnya dilakukan menggunakan objek StringBuffer atau StringBulider.
Karena sifat tidak berubah dari kelas string, ada banyak hal untuk dikatakan tentang ini. Selama Anda tahu bahwa contoh string tidak akan berubah begitu dihasilkan, misalnya: string str = "kv"+"sakit"+""+"ans"; Ada 4 konstanta string. Pertama, "KV" dan "Ill" menghasilkan "kvill" dalam memori, dan kemudian "kvill" dan "" "menghasilkan" kvill "dan" "dan" kvill ans "dihasilkan; dan alamat string ini ditugaskan ke str, karena string" tidak dapat diubah "menghasilkan banyak variabel sementara, itulah sebabnya itu direkomendasikan untuk menggunakan stringbuffer" tidak dapat diubah.
Penggunaan akhir dan pemahaman dalam string
Kode Java
Final StringBuffer A = New StringBuffer ("111"); Final StringBuffer B = New StringBuffer ("222"); a = b; // Kalimat ini tidak dikompilasi sampai selesai. Final StringBuffer A = New StringBuffer ("111"); A.Append ("222"); /// Compile Setelah selesaiDapat dilihat bahwa final hanya berlaku untuk "nilai" yang direferensikan (mis., Alamat memori). Ini memaksa referensi ke hanya menunjuk ke objek yang awalnya ditunjukkan. Mengubah penunjuknya akan menyebabkan kesalahan waktu kompilasi. Adapun perubahan objek yang ditunjukkannya, final tidak bertanggung jawab.
Meringkaskan
Tumpukan digunakan untuk menyimpan beberapa data variabel lokal dari tipe data asli dan referensi ke objek (string, array, objek, dll.) Tetapi tidak menyimpan konten objek
Objek yang dibuat menggunakan kata kunci baru disimpan di tumpukan.
String adalah kelas pembungkus khusus, dan rujukannya disimpan dalam tumpukan, dan konten objek harus ditentukan sesuai dengan metode pembuatan (kumpulan konstan dan heap). Beberapa dibuat pada waktu kompilasi dan disimpan di kumpulan string konstan, sementara yang lain hanya dibuat saat runtime. Gunakan kata kunci baru dan disimpan di tumpukan.
Artikel di atas secara singkat berbicara tentang perbedaan antara alokasi memori Java+ dan lokasi penyimpanan variabel adalah semua konten yang saya bagikan dengan Anda. Saya harap Anda dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.