Rumah  >  Artikel  >  Java  >  Cara menggunakan pemusnahan objek Java dan memuktamadkan kaedah

Cara menggunakan pemusnahan objek Java dan memuktamadkan kaedah

王林
王林ke hadapan
2023-04-15 09:58:05738semak imbas

Pemusnahan objek

Dalam C++, kaedah pemusnah digunakan untuk melepaskan sumber dan memusnahkan objek itu sendiri.

Di Jawa, disebabkan kewujudan GC, kami tidak perlu menuntut semula memori secara manual, yang mengurangkan beban kerja dan meningkatkan keselamatan program dengan banyak. Tetapi Java mempunyai fungsi yang serupa dengan pemusnah dalam C++.

memuktamadkan kaedah

Lebihkan kaedah ini untuk melaksanakan beberapa operasi apabila kelas dikitar semula oleh GC.

Berikut ialah contoh kelas memuktamadkan pelaksanaan.

Kelas Aoo mempunyai atribut int dan String Ia membebankan kepadaString dan mencetak objek serta masa penciptaannya dalam pembinaan, dan mencetak objek dan masa panggilan dimuktamadkan.

Kelas Aoo

public class Aoo {
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }
        /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
       }
}

Pertama, ujian mudah

kaedah utama

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a = new Aoo(1, "a");
              a = null;
              System.gc()
              Thread.sleep(2000);
              System.exit(0);
       }
}

Cetak hasil:

id:1 nama:a now create:1497547723036
id:1 name:anow finalize:1497547724059

GC kitar semula objek

GC dipanggil secara manual di sini untuk membersihkan memori, dan jika anda mengulas System.gc();, hasil cetakan adalah seperti ini:

id:1 name:a now create:1497547846923

Maksudnya, tanpa memanggil GC secara khusus, kaedah finalize tidak dipanggil sama sekali, yang bermaksud objek ini tidak dikitar semula secara aktif sama sekali.

Bertentangan dengan imaginasi, mod operasi GC adalah malas, maksudnya, apabila tiada tempat dalam ingatan, GC tidak akan mengitar semula objek secara aktif Untuk mengesahkan idea ini, saya mencipta Thread digunakan untuk menggunakan memori secara berterusan dan tidak memanggil GC secara aktif.

Kelas ThreadA

public class ThreadA implements Runnable{
       public void run() {
              List<Integer> list = new ArrayList<Integer>();
              int i = 0;
              while(true){
                     list.add(i);
                     i++;
              }
       }
}

kaedah utama

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a = new Aoo(1, "a");
              a = null;
              ThreadA ta = new ThreadA();
              Thread t = new Thread(ta);
              t.start();
              Thread.sleep(2000);
              System.exit(0);
       }
}

Hasil cetakan:

id:1 name:a now create:1497548135268
id:1 name:anow finalize:1497548135386

Kali ini, walaupun GC tidak dipanggil secara manual, kaedah muktamad masih berjalan, Maksudnya, GC hanya akan berjalan apabila memori digunakan dan GC perlu membersihkan memori.

Kaedah pemuktamadkan seperti itu benar-benar tidak boleh dipercayai, malah tidak pasti sama ada ia boleh dipanggil, apatah lagi menyelesaikan sebarang operasi tertentu Jika anda perlu menutup strim dan memulihkan sumber, adalah lebih baik untuk memanggil kaedah secara manual, atau dalam Sumber dikeluarkan secara seragam dalam blok akhir.

Dalam kaedah pemuktamadkan, patutkah anda menetapkan semula rujukan kepada diri anda untuk mengelak daripada dikitar semula oleh GC?

Cuba rujuk semula dalam kaedah muktamad untuk menghalang GC daripada dikitar semula

Aoo yang diubah suai adalah seperti berikut

public class Aoo {
       public static Aoo SAVE = null;
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }  
       /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
              SAVE = this;
       }
}

kaedah utama

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo.SAVE = new Aoo(1, "a");
              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );              
              System.exit(0);             
       }
}

Cetak hasil:

id:1 nama:a sekarang buat:1497551409195
id:1 nama:kini dimuktamadkan:1497551409201 >a masih hidup

Dapat dilihat di sini bahawa objek Aoo.SAVE memang "dibangkitkan", tetapi operasi sedemikian terhad Jika helah yang sama diulang, objek itu tidak akan ". dibangkitkan" lagi.

kaedah utama

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo.SAVE = new Aoo(1, "a");
              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );

              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );

              System.exit(0);          
       }
}
Hasil cetakan:

id:1 nama:a sekarang buat:1497551587715

id: 1 name:anow finalize:1497551587721
a masih hidup
a sudah mati

Perhatikan di sini bahawa kedua-dua operasi adalah sama, dan kaedah finalize hanya akan dipanggil sekali oleh sistem .

Apakah yang akan berlaku jika gelung tak terhingga berlaku dalam kaedah finalze?

Kelas Aoo

public class Aoo {
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }
       /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              while(true){
                     System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
                     Thread.sleep(100);
              }
       }
}

kaedah utama

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a1 = new Aoo(1 , "a1");
              Aoo a2 = new Aoo(2 , "a2");
              a1 = null;
              a2 = null;
              ThreadA ta = new ThreadA();
              Thread t = new Thread(ta);
              t.start();
              Thread.sleep(5000);

              System.exit(0);
       }
}
Hasil cetakan:

id:1 nama:a1now finalize:1497552026848
id:1 name:a1now finalize:1497552028960

id:1 name:a1now finalize:1497552032363
Rawaknya
adalah Kadangkala pemuktamadkan a1 dilaksanakan, dan kadangkala pemuktamadkan a2 dilaksanakan.


Hasil ini menggambarkan dua perkara:

1 Keutamaan urutan kaedah finalze adalah sangat rendah, dan selang masa agak tidak pasti dan jauh lebih besar daripada 100 milisaat. .

2. Gelung tak terhingga ini menyebabkan kaedah memuktamadkan objek lain gagal dilaksanakan.

Jika terdapat gelung tak terhingga dalam penciptaan objek, adakah ia akan menyebabkan objek tidak dapat dimusnahkan dan menyebabkan limpahan memori?

Kami mencipta sejumlah besar objek Aoo dan menunggu GC untuk menuntut semula ingatan itu dengan sendirinya.

Untuk melihat secara visual panggilan kaedah pemuktamadkan, kod cetakan apabila objek Aoo dimulakan telah dipadamkan.

kaedah utama

Biarkan program dijalankan selama kira-kira dua minit, kemudian tamatkannya secara manual dan lihat output

1497554225913
id:269614 nama:a269614sekarang dimuktamadkan:1497554226151
id:269614 nama:a269614sekarang nama:14297555:142765 269614sekarang dimuktamadkan:1497554227735
id:269614 nama :a269614sekarang dimuktamadkan:1497554227836
id:269614 nama:a269614sekarang dimuktamadkan:1497554229586
id:269614 nama:a269614nama sekarang:6🎜1429655.14296 :a269614sekarang dimuktamadkan:1497554229951
id:269614 nama:a269614now memuktamadkan:1497554230051
id:269614 nama:a269614sekarang memuktamadkan:1497554230152
id:269614 nama:a269614sekarang memuktamadkan:1497554233696 memuktamadkan:1497554233800
id:269614 nama:a269614sekarang memuktamadkan: 1497554233900
id:269614 nama:a269614kini dimuktamadkan:1497554234308
id:269614 nama:a269614sekarang dimuktamadkan:1497554234408:1497554234408 :1497554234508
id:269614 nama:a269614sekarang dimuktamadkan:1497554235053
id:269614 nama:a269614kini dimuktamadkan:1497554235153
id:269614 nama:a269614sekarang dimuktamadkan:1497554235253
id:269614 nama:269614
id:269614 nama:a269614sekarang dimuktamadkan:1497554235923
id:269614 nama:a269614sekarang dimuktamadkan:1497554236023
id:269614 nama:a269614kini dimuktamadkan:1497554240324
id:269614 nama:a269614 >id:269614 nama:a269614kini dimuktamadkan:1497554240525
id: 269614 nama:a269614kini dimuktamadkan:1497554241146
id:269614 nama:a269614sekarang dimuktamadkan:1497554241247
id:269614 nama:a269614>149614 :269614 nama:a269614sekarang dimuktamadkan:1497554241448
id:269614 nama :a269614sekarang dimuktamadkan:1497554242020
id:269614 nama:a269614sekarang dimuktamadkan:1497554242120
id:269614 nama:a2696142 nama:4249255🎜 :a269614sekarang dimuktamadkan:1497554242321
id:269614 nama:a269614now memuktamadkan:1497554242421
id:269614 nama:a269614sekarang memuktamadkan:1497554242521
id:269614 nama:a269614sekarang memuktamadkan:1497552 memuktamadkan:1497554248467
id:269614 nama:a269614sekarang memuktamadkan: 1497554248567
id:269614 nama:a269614sekarang dimuktamadkan:1497554248667
id:269614 nama:a269614sekarang dimuktamadkan:1497554249534:1497554249534:1497554249534:6 :1497554249634
id:269614 nama:a269614sekarang dimuktamadkan:1497554249734
id:269614 nama:a269614sekarang dimuktamadkan:1497554249835
id:269614 nama:a269614sekarang dimuktamadkan:1497554255954
id:269614 nama:269614:1497554255954
id:269614 nama:a269614sekarang dimuktamadkan:1497554256155
id:269614 nama:a269614sekarang dimuktamadkan:1497554256255
id:269614 nama:a269614sekarang dimuktamadkan:1497554256356
id:269614 nama:a269614 >id:269614 nama:a269614kini dimuktamadkan:1497554257386
id: 269614 nama:a269614sekarang dimuktamadkan:1497554257486
id:269614 nama:a269614sekarang dimuktamadkan:1497554257586
id:269614 nama:a269614>6.269614 :269614 nama:a269614sekarang dimuktamadkan:1497554268652
id:269614 nama :a269614sekarang dimuktamadkan:1497554268753
id:269614 nama:a269614sekarang dimuktamadkan:1497554268853
id:269614 nama:a269614nama sekarang:42614555:146955:14695 :a269614sekarang dimuktamadkan:1497554269054
id:269614 nama:a269614now memuktamadkan:1497554269154
id:269614 nama:a269614sekarang memuktamadkan:1497554277474
id:269614 nama:a269614sekarang memuktamadkan:1497552


可以发现两个情况:


1.只有一个对象的finalize方法被执行了,也就是个有一个对象的finalize方法被执行了,也就是个对象的finalize阻止了其他对象执行memuktamadkan方法

2.程序执行很快的一段时间后,memuktamadkan方法就开始执行,但是随着内存消耗的不栭存方法就开始执行,但是随着内存消耗的不断增行数也就越来越少。

Atas ialah kandungan terperinci Cara menggunakan pemusnahan objek Java dan memuktamadkan kaedah. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam