Ada empat jenis referensi di Java/Android, yaitu:
Referensi Kuat - Referensi Kuat
Referensi Lembut - Referensi Lembut
Referensi Lemah - Referensi Lemah
Referensi Phantom - Kutipan Virtual
Jenis referensi yang berbeda memiliki karakteristik yang berbeda dan juga sesuai dengan skenario penggunaan yang berbeda.
1. Referensi Strong - Referensi yang Kuat
Jenis referensi yang paling umum dalam pengkodean aktual. Bentuk umum seperti: a = a a () baru; dll. Referensi yang kuat itu sendiri disimpan dalam memori tumpukan, dan menyimpan alamat ke objek dalam memori. Secara umum, ketika tidak ada lagi referensi kuat untuk objek dalam memori yang menunjuk padanya, mesin pengumpulan sampah mulai mempertimbangkan koleksi sampah yang mungkin dilakukan pada memori ini. Jika pengkodean: a = nol, pada saat ini, alamat yang hanya dialokasikan di tumpukan dan dibuat tidak memiliki referensi lain. Saat sistem melakukan pengumpulan sampah, heap memori akan dikumpulkan sampah.
Softreference, lemah referensi, dan phantomreference adalah semua subclass dari kelas java.lang.ref.reference. Referensi, sebagai kelas dasar abstrak, mendefinisikan operasi dasar objek subkelasnya. Subkelas referensi semuanya memiliki karakteristik berikut:
1. Subkelas referensi tidak dapat dibuat secara langsung tanpa parameterisasi. Setidaknya harus menggunakan objek referensi yang kuat sebagai parameter konstruksi untuk membuat objek subkelas masing -masing;
2. Karena objek dibuat dalam 1 dengan objek referensi yang kuat sebagai parameter konstruksi, objek dalam memori heap yang ditunjukkan oleh referensi yang semula kuat tidak akan lagi terkait langsung dengan referensi yang kuat itu sendiri, tetapi juga akan memiliki koneksi tertentu dengan referensi objek subkelas referensi. Dan hubungan ini dapat mempengaruhi koleksi sampah objek.
Menurut berbagai karakteristik pengaruh dari berbagai objek subclass pada pengumpulan sampah dari objek indikatornya (referensi yang kuat untuk objek dalam memori heap ditunjuk ke), tiga subclass terbentuk, yaitu softreference, lemah referensi dan phantomreference.
2. Referensi Soft - Referensi Lembut
Bentuk penggunaan umum referensi lunak adalah sebagai berikut:
A = a a () baru;
Softreference <a> sra = softreference baru <a> (a);
Melalui referensi yang kuat dari objek sebagai parameter, objek SofTreference dibuat dan WRA di stack memori titik ke objek ini.
Pada saat ini, pengkodean berikut dilakukan: a = null. Apa dampaknya pada koleksi sampah objek yang awalnya ditunjukkan oleh A?
Mari kita lihat hasil output dari program berikut:
impor java.lang.ref.softreference; ReferenceTest kelas publik {public static void main (string [] args) {a = new a (); Softreference <a> sra = softreference baru <a> (a); a = null; if (sra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + sra.get ()); } // Garbage Collection System.gc (); if (sra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + sra.get ()); }}} kelas A {} ## Hasil outputnya adalah:
1 Objek belum didaur ulang A@4807ccf62 Objek belum didaur ulang@4807ccf6
Ketika a = nol, objek A dalam memori heap tidak akan lagi memiliki referensi yang kuat untuk itu, tetapi ada objek modis yang dirujuk oleh SRA yang menunjuk ke objek A. Ketika metode sra.get () dipanggil untuk pertama kalinya untuk mengembalikan objek indikator ini, karena pengumpul sampah cenderung belum melakukan pengumpulan sampah, get () memiliki hasil saat ini, yang mudah dimengerti. Ketika program mengeksekusi system.gc (); Memaksa pengumpulan sampah, melalui sra.get (), ditemukan bahwa objek yang ditunjukkan masih dapat diperoleh, menunjukkan bahwa objek A belum dikumpulkan. Jadi, kapan objek yang ditunjukkan oleh referensi lunak mulai dikumpulkan? Dua kondisi berikut perlu dipenuhi:
1. Ketika objek yang ditunjukkannya tidak memiliki objek referensi yang kuat yang menunjuk padanya;
2. Ketika mesin virtual memiliki memori yang tidak mencukupi.
Oleh karena itu, softreference memperpanjang waktu itu menunjukkan bahwa objek menempati memori heap sampai mesin virtual memiliki memori yang tidak mencukupi. Kolektor sampah tidak mendaur ulang ruang memori tumpukan ini.
3. Referensi Weak - Referensi Lemah
Demikian pula, bentuk penggunaan umum referensi lunak adalah sebagai berikut:
A = a a () baru;
Lemah Referensi <a> WRA = Referensi Lemah Baru <a> (a);
Ketika tidak ada referensi kuat yang menunjuk pada objek ini, apa karakteristik pengumpulan sampahnya?
impor java.lang.ref.weakreference; Referencetest kelas publik {public static void main (string [] args) {a = new a (); Lemah Referensi <a> WRA = Referensi Lemah Baru <a> (a); a = null; if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); }}} kelas A {} ## Hasil outputnya adalah:
Objek belum didaur ulang namun objek@52e5376aa memasuki proses pengumpulan sampah
Output hasil pertama dijelaskan seperti di atas. Setelah pengumpulan sampah, wra.get () akan mengembalikan nol, menunjukkan bahwa itu menunjukkan bahwa objek telah memasuki proses pengumpulan sampah. Oleh karena itu, karakteristik kutipan yang lemah dirangkum sebagai:
Referensi lemah tidak mengubah waktu pengumpulan sampah dari objek referensi kuat asli. Setelah menunjukkan bahwa objek tidak memiliki objek referensi yang kuat, objek memasuki proses pengumpulan sampah normal.
Jadi, berdasarkan karakteristik ini, ada pertanyaan: Apa pentingnya lemah?
Skenario penggunaan utamanya adalah: saat ini ada referensi kuat yang menunjuk pada objek referensi yang kuat. Pada saat ini, karena kebutuhan bisnis, perlu untuk meningkatkan referensi ke objek ini, dan pada saat yang sama, tidak dimaksudkan untuk mengubah waktu pengumpulan sampah dari referensi ini. Pada saat ini, Lemah Referensi hanya memenuhi kebutuhan dan umumnya ditemukan dalam beberapa skenario dengan siklus hidup.
Berikut ini adalah skenario untuk penggunaan lemah referensi di Android - menggabungkan kelas dalam statis dan refreferensi lemah untuk menyelesaikan kemungkinan masalah kebocoran memori pawang dalam aktivitas.
Dalam aktivitas ini, kita perlu membuat utas baru untuk mendapatkan data dan menggunakan metode Handler - SendMessage. Berikut adalah kode umum untuk proses ini:
MainActivity kelas publik memperluas aktivitas {// ... halaman int private; Private Handler Handler = New Handler () {@Override public void handlemessage (pesan msg) {if (msg.what == 1) {// ... halaman ++; } kalau tidak { //... } }; }; @Override Protected void onCreate (bundle savedInstanceState) {super.onCreate (saveDinstanceState); setContentView (r.layout.activity_main); // ... utas baru (runnable baru () {@Override public void run () {// .. pesan msg = message.obtain (); msg.what = 1; //msg.obj = xx; handler.sendMessage (msg);}). start (); // ...}}Jalankan tautan di eclispe, Anda akan melihat pesan peringatan: kelas penangan ini harus statis atau kebocoran mungkin terjadi ... klik untuk melihat informasi ini, yang menjelaskan masalah dalam detail dan memberikan solusi sugestif.
Masalah: Memastikan bahwa kelas pawang tidak berpegang pada referensi ke classid luar: HandlerLeaksince Handler ini dinyatakan sebagai kelas dalam, itu dapat mencegah kelas luar dari sampah dikumpulkan. Jika pawang menggunakan looper atau pesan untuk utas selain utas utama, maka tidak ada masalah. Jika pawang menggunakan looper atau pesan dari utas utama, Anda perlu memperbaiki deklarasi pawang Anda, sebagai berikut: menyatakan penangan sebagai kelas statis; di kelas luar, instantiate referensi lemah ke kelas luar dan berikan objek ini ke pawang Anda saat Anda instantiate handler; Buat semua referensi ke anggota kelas luar menggunakan objek Lemah Lemah.
Makna umum adalah bahwa disarankan untuk mendefinisikan pawang sebagai kelas statis internal, dan mendefinisikan referensi untuk referensi lemah di kelas dalam statis ini, karena menunjukkan objek aktivitas eksternal.
Analisis Masalah:
Aktivitas memiliki siklus hidupnya sendiri. Selama proses berjalan utas yang baru dibuka dalam aktivitas, pengguna dapat menekan tombol belakang atau sistem tidak mencukupi memori, dll. Untuk mendaur ulang aktivitas ini. Karena utas yang baru diluncurkan dalam aktivitas tidak akan mengikuti siklus aktivitas itu sendiri, yaitu, ketika aktivitas mengeksekusi OnDesroy, karena keberadaan utas dan handlemessage handler, sistem awalnya berharap untuk melakukan pemulihan memori dari kegiatan ini tidak dapat diimplementasikan, karena masalah internal non-statis secara implisit memegang referensi ke kelas eksternal, hasil hasil dalam hasil dalam hasil dalam hasil dalam kenangan.
Oleh karena itu, ketika menggunakan pawang dalam aktivitas, di satu sisi, itu perlu didefinisikan sebagai bentuk kelas dalam statis, sehingga dapat dipisahkan dari kelas eksternal dan tidak lagi memegang referensi ke kelas eksternal. Pada saat yang sama, karena handlermessage di pawang umumnya perlu mengakses atau memodifikasi sifat -sifat aktivitas, pada saat ini, referensi lemah yang menunjuk pada aktivitas ini perlu didefinisikan di dalam pawang sehingga tidak akan mempengaruhi pemulihan memori aktivitas. Pada saat yang sama, sifat -sifat kegiatan dapat diakses dalam keadaan normal.
Rekomendasi Google resmi adalah:
MainActivity kelas publik memperluas aktivitas {// ... halaman int private; private myhandler mmyhandler = myhandler baru (ini); kelas statis pribadi myhandler memperluas handler {private weastreference <Anteractivity> wractivity; MyHandler public (MainActivity Activity) {this.wractivity = New WeFreference <AnterActivity> (aktivitas); } @Override public void handlemessage (pesan msg) {if (wractivity.get () == null) {return; } MainActivity mactivity = wractivity.get (); if (msg.what == 1) {// ... mactivity.page ++; } else {// ...}}} @Override Protected void onCreate (bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (r.layout.activity_main); // ... utas baru (runnable baru () {@Override public void run () {// .. pesan msg = message.obtain (); msg.what = 1; //msg.obj = xx; mmyhandler.sendMessage (msg);}}). start (); // ...}}Untuk softreference dan lemah referensi, ada juga parameter konstruktor ReferenceQueue <T>, dan ketika objek yang ditunjukkan oleh Softreference atau Weakreference memang sampah dikumpulkan, rujukannya akan ditempatkan di ReferenceQueue. Perhatikan bahwa seperti di atas, ketika metode GET () dari Softreference atau Trefreference mengembalikan nol, itu hanya menunjukkan bahwa objek yang ditunjukkan telah memasuki proses pengumpulan sampah, dan objek mungkin tidak dikumpulkan sampah saat ini. Hanya setelah mengkonfirmasi bahwa itu telah dikumpulkan sampah, jika ReferenceQueue, rujukannya akan ditempatkan di ReferenceQueue.
Lihat contoh di bawah ini:
ReferenceTest kelas publik {public static void main (string [] args) {a = new a (); Lemah Referensi <a> WRA = Referensi Lemah Baru <a> (a); a = null; if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); }}} kelas A {@Override Protected void finalize () melempar lempar {super.finalize (); System.out.println ("dalam finalisasi"); }} ## Hasil outputnya adalah:
1 Objek belum didaur ulang a@46993aaa2 Objek telah didaur ulang 3 dalam finalisasi
Ini juga memverifikasi pernyataan "memasuki proses pengumpulan sampah" yang disebutkan di atas. Mari kita lihat sepotong kode dalam kombinasi dengan ReferenceQueue:
ReferenceTest kelas publik {public static void main (string [] args) {a = new a (); ReferenceQueue <a> rq = ReferenceQueue baru <a> (); Lemah Referensi <a> WRA = Referensi Lemah Baru <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } System.out.println ("Item RQ:" + rq.poll ()); // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } /* coba {thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); } */ System.out.println ("item rq:" + rq.poll ()); }} class a {@Override Protected void finalize () melempar lempar {super.finalize (); System.out.println ("dalam finalisasi"); }} ## Hasil outputnya adalah:
Objek belum didaur ulang namun item@302b2c81rq: objek nulla memasuki proses pengumpulan sampah RQ item: nullin a finalize
Dengan demikian, diverifikasi bahwa "referensi softreference atau lemah yang hanya memasukkan proses pengumpulan sampah belum ditambahkan ke ReferenceQueue".
ReferenceTest kelas publik {public static void main (string [] args) {a = new a (); ReferenceQueue <a> rq = ReferenceQueue baru <a> (); Lemah Referensi <a> WRA = Referensi Lemah Baru <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } System.out.println ("Item RQ:" + rq.poll ()); // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Objek memasuki proses pengumpulan sampah"); } else {System.out.println ("Objek belum didaur ulang" + wra.get ()); } coba {thread.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Item RQ:" + rq.poll ()); }} class a {@Override Protected void finalize () melempar lempar {super.finalize (); System.out.println ("dalam finalisasi"); }} ## Hasil outputnya adalah:
Objek belum didaur ulang namun item@6276E1DBRQ: Objek nulla memasuki proses pengumpulan sampah dalam item finalzerq: java.lang.ref.weakreference@645064f
Ini mengkonfirmasi pernyataan di atas.
4.Fantomreference
Dibandingkan dengan softreference atau lemah, perbedaan utama dalam phantomreference tercermin dalam poin -poin berikut:
1. Phantomreference hanya memiliki satu konstruktor phantomreference (T Reference, ReferenceQueue <? Super t> q), sehingga phantomreference harus digunakan dalam kombinasi dengan ReferenceQueue;
2. Terlepas dari apakah ada referensi yang kuat untuk objek indikator yang menunjuk ke phantomreference, metode get () dari phantomreference mengembalikan hasil nol.
ReferenceTest kelas publik {public static void main (string [] args) {a = new a (); ReferenceQueue <a> rq = ReferenceQueue baru <a> (); Phantomreference <a> pra = Phantomreference baru <a> (a, rq); System.out.println ("pra.get ():" + pra.get ()); a = null; System.gc (); coba {thread.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Item RQ:" + rq.poll ()); }} kelas A {} ## Hasil outputnya adalah:
pra.get (): item nullrq: java.lang.ref.phantomreference@1da12fc0
Thread.sleep (1); Dalam fungsi kode yang sama seperti pada contoh di atas, dan keduanya memastikan bahwa utas pengumpulan sampah dapat dijalankan. Jika tidak, referensi virtual ke objek indikator yang memasukkan proses pengumpulan sampah tanpa benar -benar sampah yang dikumpulkan tidak akan ditambahkan ke phantomreference.
Seperti Lemah Referensi, phantomreference tidak mengubah waktu pengumpulan sampah dari objek indikasi. Dapat disimpulkan bahwa fungsi ReferenceQueUe terutama digunakan untuk mendengarkan softreference/weakreference/phantomreference yang menunjukkan apakah objek telah dikumpulkan sampah.
Di atas adalah konten lengkap dari analisis komprehensif jenis referensi Java/Android dan penggunaan yang dibawa kepada Anda oleh editor. Saya harap ini akan membantu Anda dan mendukung wulin.com lebih banyak ~