Cet article présente principalement l'interdiction d'utiliser la méthode finalize en Java. Les amis qui en ont besoin peuvent s'y référer
Qu'est-ce que la méthode finalize
finalize La méthode () est définie dans la classe Java.lang.Object, ce qui signifie que toutes les classes peuvent remplacer cette méthode. Le garbage collector Java ne peut libérer que la mémoire allouée via new, donc si votre objet n'est pas une mémoire obtenue via new, alors le garbage collector ne sait pas comment libérer la mémoire de l'objet.
Afin de faire face à cette situation, Java permet à la méthode finalize() de la classe java.lang.Object d'être surchargée dans la classe.
Comment ça marche : Une fois que le garbage collector est prêt à libérer l'espace de stockage occupé par l'objet, sa méthode finalize() sera appelée en premier, et la mémoire occupée par l'objet ne sera réellement récupérée que lorsque le la prochaine action de collecte des ordures se produit.
Mécanisme d'appel de la fonction de finalisation
La spécification de la machine virtuelle Java ne stipule pas strictement si le garbage collection doit être effectué et comment il doit être effectué . Par conséquent, il n’est pas garanti que le mécanisme d’appel mentionné ici soit adapté à toutes les JVM.
Quand est-ce qu'on l'appelle ?
Quand la finalisation sera-t-elle appelée ? D'une manière générale, il ne peut pas être appelé tant que la JVM n'a pas démarré le garbage collection. Le moment auquel la JVM effectue le garbage collection est très incertain et dépend de divers facteurs environnementaux d'exécution. C'est précisément à cause de l'incertitude du moment d'appel de la fonction finalize que cela conduit à certaines des lacunes mentionnées plus loin.
Qui va appeler ?
Common JVM appellera la fonction de finalisation via le thread de récupération de place GC. Étant donné que le thread de récupération de place est très important (il fait également partie intégrante de la JVM après tout), afin d'éviter que l'exception levée par la fonction finalize n'affecte le fonctionnement du thread de récupération de place, le thread de récupération de place effectuera un essayez catch lors de l'appel de chaque fonction de finalisation.Si Lorsqu'une exception est interceptée, elle est directement ignorée, puis la fonction de finalisation du prochain objet non valide est traitée.
Pourquoi est-il interdit d'utiliser finalize()
1 L'heure d'appel est incertaine --- il y a un risque. de gaspillage de ressources
Le mécanisme d'appel a déjà été introduit. Les étudiants doivent reconnaître le fait que « le moment de la finalisation de l'appel est très incertain ». Par conséquent, si vous libérez des ressources rares dans finalize(), les ressources rares peuvent attendre très, très, très longtemps avant d'être libérées. C'est un gaspillage de ressources ! De plus, les ressources portées par certains objets de classe (comme certaines classes JDBC) peuvent elles-mêmes consommer beaucoup de mémoire, et la libération retardée de ces ressources entraînera de gros problèmes de performances.
2. Peut ne pas être appelé - il existe un risque de fuite de ressources
De nombreux étudiants pensent que finalize() sera toujours appelé, mais ce n'est pas le cas. . Dans certains cas, finalize() n'est pas appelée du tout. Par exemple, lorsque la JVM se termine, les fonctions de finalisation de ces objets en mémoire ne peuvent pas être appelées.
On estime que certains étudiants pensent à "runFinalizersOnExit" pour s'assurer que toutes les finalisations sont appelées avant la sortie de la JVM. Il est dommage et regrettable que cette méthode ait été abandonnée depuis le JDK 1.2. Même si cette méthode n'est pas abandonnée, elle présente toujours un énorme risque pour la sécurité des threads !
Comme le montre ce qui précède, une fois que vous comptez sur finalize() pour vous aider à libérer des ressources, c'est très mauvais (il y a un risque de fuite de ressources) ! Souvent, les problèmes de performances causés par des fuites de ressources sont plus graves et ne doivent pas être sous-estimés.
3. L'objet peut être ressuscité lorsque la fonction de finalisation est appelée
À l'origine, uniquement lorsqu'un objet a expiré (pas de références), le garbage collector appellera le fonction de finalisation de l'objet. Cependant, si vous rencontrez un programmeur pervers et réenregistrez la propre référence de l'objet (c'est-à-dire ceci) quelque part dans la fonction finalize(), cela équivaut à vous ressusciter (car l'objet a une nouvelle référence et n'est plus dans un fichier invalide). État). Afin d'éviter que cette chose étrange ne se produise, le ramasse-miettes ne peut vérifier si l'objet est toujours dans un état invalide qu'après chaque appel à finalize(). Cela augmente virtuellement la surcharge de la JVM. Mentionnez-le simplement avec désinvolture. Comme le stipule la documentation du JDK, la JVM n'appellera finalize() qu'une seule fois pour chaque instance d'objet de classe. Par conséquent, pour les cas de faux cadavres, finalize() ne sera pas appelé lorsqu'ils mourront réellement. Cela ne semble-t-il pas bizarre ?
4. N'oubliez pas de détecter les exceptions vous-même
Je viens de mentionner lors de l'introduction du mécanisme d'appel finalize() qu'une fois qu'une exception est levée en dehors de la fonction finalize, elle sera Attrapé et supprimé par le thread de récupération de place. En d’autres termes, l’exception est ignorée (les dangers des exceptions ignorées sont mentionnés « ici »). Afin d'éviter ce genre de chose, vous devez écrire une instruction try catch pour tout code susceptible de lever une exception dans finalize() et l'attraper vous-même.
5. Faites attention à la sécurité des fils
Puisque finalize() est appelé par un thread de garbage collection, ce n'est pas le même thread que votre propre code ; même finalize() de différents objets peut être appelé par différents threads de garbage collection (comme en utilisant un "collecteur parallèle" quand). Par conséquent, lorsque vous accédez à certaines données dans finalize(), vous devez toujours faire attention aux problèmes de sécurité des threads.
Résumé
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!