Maison  >  Article  >  Java  >  Comment utiliser les méthodes de destruction et de finalisation d'objets Java

Comment utiliser les méthodes de destruction et de finalisation d'objets Java

王林
王林avant
2023-04-15 09:58:05738parcourir

Destruction d'objets

En C++, la méthode destructeur est utilisée pour libérer des ressources et détruire l'objet lui-même.

En Java, grâce à l'existence de GC, nous n'avons pas besoin de récupérer manuellement de la mémoire, ce qui réduit considérablement la charge de travail et améliore la sécurité du programme. Mais Java a une fonction similaire au destructeur en C++.

Méthode finalize

Surchargez cette méthode pour effectuer certaines opérations lorsque la classe est recyclée par GC.

Ce qui suit est un exemple de classe implémentant finalize.

La classe Aoo a un attribut int et un attribut String. Elle surcharge toString et imprime l'objet et son heure de création dans la construction, et imprime l'objet et l'heure d'appel dans finalize.

Classe 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());
       }
}

Tout d'abord, un test simple

méthode principale

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);
       }
}

Résultat d'impression :

id:1 nom:a maintenant créer:1497547723036
id:1 nom:anow finaliser:1497 54 7724059

Recyclage d'objets GC

Ici, le GC est appelé manuellement pour nettoyer la mémoire, et si vous commentez System.gc();, le résultat imprimé est comme ceci :

id:1 name:a now create: 1497547846923

C'est-à-dire que sans appeler spécifiquement GC, la méthode finalize n'est pas appelée du tout, ce qui signifie que cet objet n'est pas du tout recyclé activement.

Contrairement à l'imagination, le mode de fonctionnement de GC est paresseux, c'est-à-dire que lorsqu'il n'y a pas de place dans la mémoire, GC ne recyclera pas activement les objets Afin de vérifier cette idée, j'ai créé un fil pour Consomme continuellement de la mémoire. et n'appelle pas activement GC. Classe ThreadA

Bien qu'il n'y ait pas de manuel opération cette fois Le GC est appelé, mais la méthode finalize est toujours en cours d'exécution. En d'autres termes, le GC ne s'exécutera que lorsque la mémoire est consommée et que le GC doit nettoyer la mémoire.

Une telle méthode de finalisation est vraiment peu fiable. Il n'est même pas sûr qu'elle puisse être appelée, et encore moins effectuer une opération spécifique. Si vous devez fermer le flux et récupérer des ressources, il est préférable d'appeler une méthode manuellement ou de l'unifier. dans le bloc final.

Dans la méthode finalize, devez-vous vous réattribuer une référence pour éviter d'être recyclé par GC ?

Essayez de re-référencer dans la méthode finalize pour empêcher GC de recycler

L'Aoo modifié est le suivant


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

méthode principale

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);
       }
}

Résultat d'impression :

id:1 nom:a maintenant créer :1497551409195

id:1 name:anow finalize:1497551409201

a est vivant

On voit ici que l'objet Aoo.SAVE est bien "ressuscité", mais une telle opération est limitée Si la même astuce est répétée, il ne sera pas "ressuscité" à nouveau l'objet.

Méthode principale re

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;
       }
}
E

Résultats d'impression :

id : 1 nom : a now create : 1497551587715

ID : 1 nom : any Les deux opérations sont les mêmes et la méthode finalize ne sera appelée qu'une seule fois par le système.

Que se passera-t-il si une boucle infinie se produit dans la méthode finalze ?

Classe Aoo

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);             
       }
}
méthode principale

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);          
       }
}

Résultat d'impression :


id:1 nom:a1 maintenant créer:1497552024252
id:2 nom:a2 maintenant créer:1497552024252
id : 1 nom :a1now finaliser:1497552024373

id:1 nom:a1now finaliser:1497552024503
id:1 nom:a1now finaliser:1497552026848

id:1 nom:a1now finaliser:1497552028960

id:1 nom:a1now finaliser:14975520 32363

Le résultat est random , parfois la finalisation de a1 est exécutée, et parfois la finalisation de a2 est exécutée.

Ce résultat illustre deux points :

1. La priorité du thread de la méthode finalze est très faible, et l'intervalle de temps est assez incertain et évidemment supérieur à 100 millisecondes.

2. Cette boucle infinie empêche l'exécution de la méthode finalize des autres objets.

S'il existe une telle boucle infinie dans la création d'objets, cela empêchera-t-il la destruction de l'objet et provoquera-t-il un débordement de mémoire ?


Nous créons un grand nombre d'objets Aoo et attendons que le GC récupère la mémoire par lui-même.

Afin d'observer visuellement l'appel de la méthode finalize, le code d'impression lors de l'initialisation de l'objet Aoo a été supprimé.


méthode principale

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);
              }
       }
}

Laissez le programme s'exécuter pendant environ deux minutes, puis terminez-le manuellement et vérifiez le résultat

1497554225913
id:269614 nom:a269614maintenant finaliser:1497554226151
id:269614 nom:a269614maintenant finaliser:1497554227635
id:269614 nom:a269614maintenant finaliser: 1497554227735
id:269614 nom:a269614maintenant finaliser:1497554227836
id:269614 nom:a269614maintenant finaliser:1497554229586
id:269614 nom:a269614maintenant finaliser:1497554229686
id:269614 nom:a269614maintenant finaliser:1497554229951
id:269614 nom:a269614maintenant finaliser:149755 4230051
id:269614 nom:a269614maintenant finaliser:1497554230152
id:269614 nom:a269614maintenant finaliser:1497554233699
id:269614 nom:a269614maintenant finaliser:1497554233800
id:269614 nom:a269614maintenant finaliser:1497554233900
id:269614 nom:a269614maintenant finaliser:149755 4234308
id:269614 nom:a269614maintenant finaliser:1497554234408
id:269614 nom:a269614maintenant finaliser:1497554234508
id:269614 nom:a269614maintenant finaliser:1497554235053
id:269614 nom:a269614maintenant finaliser:1497554235153
id:269614 nom:a269614maintenant finaliser:149755 4235253
id:269614 nom:a269614maintenant finaliser:1497554235823
id:269614 nom:a269614maintenant finaliser:1497554235923
id:269614 nom:a269614maintenant finaliser:1497554236023
id:269614 nom:a269614maintenant finaliser:1497554240324
id:269614 nom:a269614maintenant finaliser:149755 4240424
id:269614 nom:a269614maintenant finaliser:1497554240525
id:269614 nom:a269614maintenant finaliser:1497554241146
id:269614 nom:a269614maintenant finaliser:1497554241247
id:269614 nom:a269614maintenant finaliser:1497554241347
id:269614 nom:a269614maintenant finaliser:149755 4241448
id:269614 nom:a269614maintenant finaliser:1497554242020
id:269614 nom:a269614maintenant finaliser:1497554242120
id:269614 nom:a269614maintenant finaliser:1497554242220
id:269614 nom:a269614maintenant finaliser:1497554242321
id:269614 nom:a269614maintenant finaliser:149755 4242421
id:269614 nom:a269614maintenant finaliser:1497554242521
id:269614 nom:a269614maintenant finaliser:1497554248367
id:269614 nom:a269614maintenant finaliser:1497554248467
id:269614 nom:a269614maintenant finaliser:1497554248567
id:269614 nom:a269614maintenant finaliser:149755 4248667
id:269614 nom:a269614maintenant finaliser:1497554249534
id:269614 nom:a269614maintenant finaliser:1497554249634
id:269614 nom:a269614maintenant finaliser:1497554249734
id:269614 nom:a269614maintenant finaliser:1497554249835
id:269614 nom:a269614maintenant finaliser:149755 4255954
id:269614 nom:a269614maintenant finaliser:1497554256055
id:269614 nom:a269614maintenant finaliser:1497554256155
id:269614 nom:a269614maintenant finaliser:1497554256255
id:269614 nom:a269614maintenant finaliser:1497554256356
id:269614 nom:a269614maintenant finaliser:149755 4257285
id:269614 nom:a269614maintenant finaliser:1497554257386
id:269614 nom:a269614maintenant finaliser:1497554257486
id:269614 nom:a269614maintenant finaliser:1497554257586
id:269614 nom:a269614maintenant finaliser:1497554257686
id:269614 nom:a269614maintenant finaliser:149755 4268652
id:269614 nom:a269614maintenant finaliser:1497554268753
id:269614 nom:a269614maintenant finaliser:1497554268853
id:269614 nom:a269614maintenant finaliser:1497554268953
id:269614 nom:a269614maintenant finaliser:1497554269054
id:269614 nom:a269614maintenant finaliser:149755 4269154
id:269614 nom:a269614maintenant finaliser:1497554277474
id:269614 nom:a269614maintenant finaliser:1497554292852
id:269614 nom:a269614maintenant finaliser:1497554301062

可以发现两个情况:

1.只有一个Il s'agit de finaliser la finalisation. 2. Finalize方法

2.断增加,finalize方法被执行的次数也就越来越少。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer