J'ai besoin de savoir quand la finalize()
méthode est appelée dans le JVM
. J'ai créé une classe de test qui écrit dans un fichier lorsque la finalize()
méthode est appelée en la remplaçant. Il n'est pas exécuté. Quelqu'un peut-il me dire pourquoi il ne s'exécute pas?
330
finalize()
et la collecte des ordures n'a aucun impact.Réponses:
En général, il est préférable de ne pas compter sur
finalize()
le nettoyage, etc.Selon le Javadoc (qu'il vaut la peine de lire), c'est:
Comme l'a souligné Joachim, cela peut ne jamais se produire dans la vie d'un programme si l'objet est toujours accessible.
En outre, le garbage collector n'est pas garanti pour fonctionner à un moment spécifique. En général, ce que j'essaie de dire, ce n'est
finalize()
probablement pas la meilleure méthode à utiliser en général, sauf si vous avez besoin de quelque chose de spécifique.la source
finalize
cela serait utile?finalize()
méthode on pour la classe principale est invoquée lorsqu'une >> instance << de la classe est récupérée, et non lorsque la méthode principale se termine. De plus, la classe principale peut être récupérée avant la fin de l'application; par exemple, dans une application multithread où le thread "principal" crée d'autres threads puis revient. (En pratique, un chargeur de classe non standard serait requis ....)La
finalize
méthode est appelée lorsqu'un objet est sur le point de récupérer les ordures. Cela peut être à tout moment après qu'il soit devenu éligible pour la collecte des ordures.Notez qu'il est tout à fait possible qu'un objet ne soit jamais récupéré (et donc
finalize
n'est jamais appelé). Cela peut se produire lorsque l'objet ne devient jamais éligible pour gc (car il est accessible pendant toute la durée de vie de la JVM) ou lorsqu'aucune récupération de place ne s'exécute réellement entre le moment où l'objet devient éligible et le moment où la JVM cesse de s'exécuter (cela se produit souvent avec simple programmes de test).Il existe des moyens de dire à la JVM de s'exécuter
finalize
sur des objets auxquels elle n'a pas encore été appelée, mais leur utilisation n'est pas non plus une bonne idée (les garanties de cette méthode ne sont pas très fortes non plus).Si vous comptez sur
finalize
le bon fonctionnement de votre application, vous faites quelque chose de mal.finalize
devrait uniquement être utilisé pour le nettoyage des ressources (généralement non Java). Et c'est exactement parce que la JVM ne garantit pas que l'finalize
on appelle jamais un objet.la source
Closable
interface (et l'idée derrière elle) est probablement ce que vous voulez: faire.close()
fermer / supprimer la ressource et demander à l'utilisateur de votre classe de l'appeler au bon moment. Vous voudrez peut -être ajouter unefinalize
méthode "juste pour être enregistré", mais ce serait plus un outil de débogage qu'un correctif réel (car il n'est pas assez fiable).System.gc()
pour appeler FileInputStream :: finalize (), puis j'ai pu déplacer le fichier.extrait de: http://www.janeg.ca/scjp/gc/finalize.html
Vous pouvez également consulter cet article:
la source
La
finalize()
méthode Java n'est pas un destructeur et ne doit pas être utilisée pour gérer la logique dont dépend votre application. La spécification Java indique qu'il n'y a aucune garantie que lefinalize
méthode est appelée du tout pendant la durée de vie de l'application.Ce que vous voulez probablement, c'est une combinaison de
finally
et une méthode de nettoyage, comme dans:la source
Consultez Efficace Java, 2e édition, page 27. Point 7: Évitez les finaliseurs
Pour mettre fin à une ressource, utilisez plutôt try-finally:
la source
La méthode de finalisation sera appelée après que le GC détecte que l'objet n'est plus accessible et avant qu'il ne récupère réellement la mémoire utilisée par l'objet.
Si un objet ne devient jamais inaccessible,
finalize()
il ne sera jamais appelé dessus.Si le GC ne fonctionne pas, il se
finalize()
peut qu'il ne soit jamais appelé. (Normalement, le GC ne s'exécute que lorsque la JVM décide qu'il y a probablement suffisamment de déchets pour que cela en vaille la peine.)Il peut s'écouler plus d'un cycle GC avant que le GC détermine qu'un objet spécifique est inaccessible. (Les GC Java sont généralement des collecteurs "générationnels" ...)
Une fois que le GC détecte qu'un objet est inaccessible et finalisable, il est placé dans une file d'attente de finalisation. La finalisation se produit généralement de manière asynchrone avec le GC normal.
(La spécification JVM permet en fait à une JVM de ne jamais exécuter les finaliseurs ... à condition qu'elle ne récupère pas l'espace utilisé par les objets. Une JVM qui a été implémentée de cette façon serait paralysée / inutile, mais si ce comportement est "autorisé" .)
Le résultat est qu'il n'est pas judicieux de s'appuyer sur la finalisation pour faire les choses qui doivent être faites dans un délai défini. Il est préférable de ne pas les utiliser du tout. Il devrait y avoir une meilleure façon (c'est-à-dire plus fiable) de faire tout ce que vous essayez de faire dans la
finalize()
méthode.La seule utilisation légitime pour la finalisation est de nettoyer les ressources associées aux objets qui ont été perdus par le code d'application. Même alors, vous devriez essayer d'écrire le code d'application afin qu'il ne perde pas les objets en premier lieu. (Par exemple, utilisez Java 7+ try-with-resources pour vous assurer qu'il
close()
est toujours appelé ...)C'est difficile à dire, mais il y a quelques possibilités:
la source
Comme il y a une incertitude dans l'appel de la méthode finalize () par JVM (je ne sais pas si finalize () qui est surchargé sera exécuté ou non), à des fins d'étude, la meilleure façon d'observer ce qui se passe lorsque finalize () est appelé, est de forcer la JVM à appeler le garbage collection par commande
System.gc()
.Plus précisément, finalize () est appelée lorsqu'un objet n'est plus utilisé. Mais lorsque nous essayons de l'appeler en créant de nouveaux objets, il n'y a aucune certitude de son appel. Donc, pour plus de certitude, nous créons un
null
objetc
qui n'a évidemment aucune utilité future, d'où nous voyons l'c
appel de finalisation de l'objet .Exemple
Production
Remarque - Même après l'impression jusqu'à 70 et après laquelle l'objet b n'est pas utilisé dans le programme, il y a une incertitude que b est effacé ou non par la JVM puisque "la méthode de finalisation appelée dans la classe Bike ..." n'est pas imprimée.
la source
System.gc();
n'est pas une garantie que la récupération de place sera réellement exécutée.finalize imprimera le décompte pour la création de la classe.
principale
Comme vous pouvez le voir. Les résultats suivants montrent que le GC a été exécuté la première fois lorsque le nombre de classes est de 36.
la source
Ayant récemment lutté avec les méthodes du finaliseur (afin de disposer des pools de connexions pendant les tests), je dois dire que le finaliseur manque de beaucoup de choses. En utilisant VisualVM pour observer ainsi qu'en utilisant des références faibles pour suivre l'interaction réelle, j'ai constaté que les choses suivantes sont vraies dans un environnement Java 8 (Oracle JDK, Ubuntu 15):
Pensée finale
La méthode de finalisation n'est pas fiable mais ne peut être utilisée que pour une seule chose. Vous pouvez vous assurer qu'un objet a été fermé ou éliminé avant d'être récupéré, ce qui permet d'implémenter une sécurité intégrée si les objets avec un cycle de vie plus complexe impliquant une action de fin de vie sont traités correctement. C'est la seule raison pour laquelle je pense que cela en vaut la peine pour l'emporter.
la source
Un objet devient éligible pour le garbage collection ou le GC s'il n'est pas accessible à partir de threads en direct ou de toute référence statique en d'autres termes, vous pouvez dire qu'un objet devient éligible pour le garbage collection si toutes ses références sont nulles. Les dépendances cycliques ne sont pas comptées comme référence, donc si l'objet A a la référence de l'objet B et que l'objet B a la référence de l'objet A et qu'ils n'ont aucune autre référence active, les deux objets A et B seront éligibles pour la collecte des ordures. Généralement, un objet devient éligible pour le garbage collection en Java dans les cas suivants:
la source
final
champ d'un objet est utilisé à plusieurs reprises au cours d'un calcul lent, et que l'objet ne sera jamais utilisé après cela, l'objet serait-il maintenu en vie jusqu'à la dernière demande du code source par le code source, ou le JIT pourrait-il copier le champ dans un variable temporaire puis abandonner l'objet avant le calcul?GC.KeepAlive()
fonction qui ne fait que forcer le GC à supposer qu'il pourrait utiliser un objet, mais je ne connais aucune fonction de ce type en Java. On pourrait utiliser unevolatile
variable à cette fin, mais utiliser une variable uniquement à cette fin semblerait un gaspillage.FinalizerReference
, de sorte qu'il n'a pas besoin d'un cycle GC pour découvrir qu'il n'y a pas références. La synchronisation est suffisante pour assurer une relation qui se produit avant ; puisque la finalisation peut (en fait) s'exécuter dans un thread différent, elle est souvent formellement nécessaire de toute façon. Java 9 va ajouterReference.reachabilityFence
…Finalize
serait du tout appelé si le JIT produisait du code qui le faisait directement. Le code de synchronisation serait-il généralement attendu pour les objets qui ne s'attendent à être utilisés que dans un seul thread? Si un objet effectue une action qui doit être annulée avant d'être abandonnée (par exemple, ouvrir une connexion socket et acquérir une utilisation exclusive de la ressource à l'autre extrémité), avoir un finaliseur fermer la connexion pendant que le code utilise toujours le socket serait un désastre . Serait-il normal que le code utilise la synchronisation ...La méthode de finalisation n'est pas garantie. Cette méthode est appelée lorsque l'objet devient éligible pour GC. Il existe de nombreuses situations où les objets peuvent ne pas être récupérés.
la source
Parfois, lorsqu'il est détruit, un objet doit effectuer une action. Par exemple, si un objet possède une ressource non java telle qu'un descripteur de fichier ou une police, vous pouvez vérifier que ces ressources sont libérées avant de détruire un objet. Pour gérer de telles situations, java propose un mécanisme appelé "finalisation". En le finalisant, vous pouvez définir des actions spécifiques qui se produisent lorsqu'un objet est sur le point d'être supprimé du garbage collector. Pour ajouter un finaliseur à une classe, définissez simplement le finalize () que méthode . Le temps d'exécution Java appelle cette méthode chaque fois qu'il est sur le point de supprimer un objet de cette classe. Dans la méthode finalize ()vous spécifiez les actions à effectuer avant de détruire un objet. Le garbage collector est périodiquement recherché pour les objets qui ne font plus référence à aucun état en cours d'exécution ou indirectement à tout autre objet avec référence. Avant la publication d'un actif, le runtime Java appelle la méthode finalize () méthode sur l'objet. Lafinalize () sous la forme générale suivante:
Avec le mot-clé protégé , l'accès à finalize () par un code en dehors de sa classe est empêché. Il est important de comprendre que finalize () est appelé juste avant le garbage collection. Il n'est pas appelé lorsqu'un objet quitte la portée, par exemple. Cela signifie que vous ne pouvez pas savoir quand, ou si, finalize () sera exécuté. Par conséquent, le programme doit fournir d'autres moyens pour libérer des ressources système ou d'autres ressources utilisées par l'objet. Vous ne devez pas compter sur finalize () pour un fonctionnement normal du programme.
la source
Classe où nous remplaçons la méthode de finalisation
Les chances de finaliser la méthode sont appelées
lorsque la mémoire est surchargée d'objets de vidage, le GC appellera la méthode finalize
exécutez et voyez la console, où vous ne trouvez pas la méthode finalize appelée fréquemment, lorsque la mémoire est surchargée, la méthode finalize sera appelée.
la source
La source
la source
finalize()
est appelé juste avant la récupération de place. Il n'est pas appelé lorsqu'un objet sort du domaine. Cela signifie que vous ne pouvez pas savoir quand ni même sifinalize()
elle sera exécutée.Exemple:
Si votre programme se termine avant que le ramasse-miettes ne se produise, il
finalize()
ne s'exécutera pas. Par conséquent, il doit être utilisé comme procédure de sauvegarde pour garantir la bonne gestion des autres ressources, ou pour des applications à usage spécial, et non comme moyen que votre programme utilise dans son fonctionnement normal.la source
Comme indiqué dans https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers ,
la source
Essayez d'exécuter ce programme pour une meilleure compréhension
la source