Est-il destructeur pour Java?
Est-il destructeur pour Java? Je ne semble pas être en mesure de trouver toute la documentation sur ce sujet. Si il n'y en a pas, comment puis-je obtenir le même effet?
Pour faire à ma question plus spécifique, je suis en train d'écrire une application qui traite les données et les spécifications de dire qu'il devrait y avoir un bouton "réinitialiser" qui apporte de l'application à son origine vient de lancer état. Cependant, toutes les données doivent être "en direct", sauf si l'application est fermée ou réinitialiser le bouton est pressé.
Étant généralement un C/C++ programmeur, je pensais que ce serait facile à implémenter. (Et j'ai donc prévu de mettre en œuvre ce dernier.) J'ai structuré mon programme tel que le "reset" en mesure les objets seraient dans la même classe, ce que je peux juste détruire tous les "en direct" des objets lorsqu'un bouton est pressé.
Je pensais, si j'ai tout juste à déréférencer les données et d'attendre que le garbage collector pour les recueillir, ne serait-il pas être une fuite de mémoire si mon utilisateur à plusieurs reprises les données entrées et appuyé sur le bouton de réinitialisation? Je pensais aussi depuis Java est assez mature comme un langage, il devrait y avoir un moyen d'empêcher que cela se produise ou gracieusement de s'attaquer à ce.
- Le terme est "destructeur", pas "déconstructeur". Mais alors que vous saviez qu'.
- Il n'existe qu'une fuite de mémoire si vous détenez des références à des objets que vous n'avez pas besoin. c'est à dire Il y a un bug dans votre programme. Le GC exécuter comme il faut (parfois plus tôt)
- La machine virtuelle ne sera pas exécuté GC assez tôt si vous êtes rapidement le traitement de données à travers des objets. L'idée que le GC peut toujours suivre, ou de prendre les bonnes décisions est une illusion.
- Ne serait pas JVM exécuter GC avant de donner une erreur?
- Ouais, ce serait bien si il y avait destructeur pour Java qui voudraient la détruire une fois pour toutes.
Vous devez vous connecter pour publier un commentaire.
Parce que Java est un de ces ordures de la langue vous ne pouvez pas prédire quand (ou si) d'un objet sera détruit. Donc il n'y a pas d'équivalent direct d'un destructeur.
Il y a une méthode héritée appelé
finalize
, mais ceci est appelé entièrement à la discrétion du garbage collector. Donc, pour les classes qui doivent explicitement ranger, la convention est de définir une près méthode et l'utilisation de finaliser seulement pour la santé mentale de contrôle (c'est à dire si près n'a pas été appelé à le faire maintenant et journal d'une erreur).Il y avait une question qui a engendré une discussion en profondeur de finaliser récemment, ce qui devrait donner plus de profondeur si nécessaire...
finalize
méthode a été dépréciées en Java 9.Ont un look à la try-with-resources déclaration. Par exemple:
Ici, la ressource est plus nécessaire, il est libéré dans le
BufferedReader.close()
méthode. Vous pouvez créer votre propre classe qui implémenteAutoCloseable
et l'utiliser dans un mode similaire.Cette déclaration est plus limitée que
finalize
en termes de code de la structuration, mais en même temps, elle rend le code plus simple à comprendre et à maintenir. Aussi, il n'y a aucune garantie qu'unefinalize
méthode est appelée lors de la livetime de l'application.with
, qui, je l'aime.try
et lafinally
est utilisé pour forcer un appel àobj.finalize()
. Et même cette configuration ne permet pas de résoudre le problème posé par l'OP: destruction des objets à mi-programme déclenché par un bouton "reset".Nope, pas de destructeurs ici. La raison en est que tous les objets Java sont des tas alloués et les ordures collectées. Sans l'accord de libération de la mémoire (c'est à dire C++opérateur delete) il n'y a pas de meilleure façon de mettre en œuvre de véritables destructeurs.
Java prend en charge les finaliseurs, mais ils sont conçus pour être utilisés seulement comme une clause de sauvegarde pour des objets ayant une poignée de ressources autochtones comme les prises, les descripteurs de fichiers, poignées de fenêtre, etc. Lorsque le garbage collector recueille un objet sans un finaliseur il marque simplement la zone de mémoire libre et c'est tout. Lorsque l'objet a un finaliseur, c'est d'abord copié dans un emplacement temporaire, (rappelez-vous, nous sommes à la collecte des ordures ici), puis il est mis en file d'attente en attente d'être finalisé file d'attente, puis un Finaliseur fil des sondages de la file d'attente avec priorité très basse et exécute l'outil de finalisation.
Lorsque l'application se ferme, la machine s'arrête sans attente pour les objets en cours d'être finalisé, donc il n'y a pratiquement aucune garantie que votre finaliseurs sera jamais exécuté.
Utilisation de finalize() méthodes doit être évitée. Ils ne sont pas un mécanisme fiable de ressources nettoyer et il est possible de provoquer des problèmes dans le garbage collector en abuser.
Si vous avez besoin d'une libération de l'appel dans votre objet, dire à libérer des ressources, l'utilisation explicite de l'appel de méthode. La présente convention peut être vu dans les APIs existantes (par exemple,Fermer, Les graphiques.dispose(), Widget de.dispose()) et est généralement appelé via le try/finally.
Tentatives d'utilisation d'un objet supprimé doit lancer une exception d'exécution (voir IllegalStateException).
EDIT:
Généralement, tout ce que vous devez faire est de déréférencer les objets - au moins, ce est la façon dont il est censé fonctionner. Si vous êtes inquiet au sujet de la collecte des ordures, découvrez Java SE 6 HotSpot[tm] de la Machine Virtuelle de Collecte des Ordures Tuning (ou le document équivalent pour votre version de la JVM).
class Resource { finalize() { destroy(); } protected native void destroy(); } class Alt_Resource { try (Resource r = new Resource()) { // use r } finalize { r.destroy(); }
Avec Java 1.7 publié, vous avez maintenant l'option supplémentaire de l'utilisation de la
try-with-resources
bloc. Par exemple,Si vous exécutez cette classe,
c.close()
sera exécutée lorsque latry
bloc est à gauche, et avant lacatch
etfinally
blocs sont exécutés. Contrairement au cas de lafinalize()
méthode,close()
est garanti d'être exécuté. Cependant, il n'est pas nécessaire de l'exécuter de manière explicite dans lefinally
clause.finalize()
exécutionJe suis entièrement d'accord pour les autres réponses, en disant de ne pas compter sur l'exécution de finaliser.
En plus de try-catch-finally blocs, vous pouvez utiliser Runtime#addShutdownHook (introduit dans Java 1.3) pour effectuer final le nettoyage dans votre programme.
Qui n'est pas le même que les destructeurs sont, mais on peut mettre en œuvre un crochet d'arrêt d'avoir les objets écouteurs enregistrés sur laquelle des méthodes de nettoyage (fermer les connexions persistantes aux bases de données, supprimer les verrous de fichier, et ainsi de suite) peuvent être invoqués choses que devrait normalement être fait dans les destructeurs.
Encore une fois - ce n'est pas un remplacement pour les destructeurs, mais dans certains cas, vous pouvez aborder le voulais à la fonctionnalité de ce.
L'avantage, c'est d'avoir la déconstruction comportement faiblement couplé du reste de votre programme.
Non,
java.lang.Objet#finaliser
est le plus proche que vous pouvez obtenir.Cependant, quand (et si) il est appelé, n'est pas garanti.
Voir:
java.lang.Runtime#runFinalizersOnExit(boolean)
Tout d'abord, notez que, depuis Java est le garbage collector, il est rare d'avoir besoin de faire quelque chose au sujet de l'objet de destruction. D'abord parce que vous n'avez pas l'habitude d'avoir toutes les ressources gérées gratuit, et ensuite parce que vous ne pouvez pas prédire quand il va arriver, il est donc inapproprié pour des choses que vous avez besoin de se "dès que personne n'est à l'aide de mon objet plus".
Vous pouvez être notifié après qu'un objet a été détruit à l'aide de java.lang.réf.PhantomReference (en fait, en disant qu'il a été détruit peut être légèrement inexacte, mais si un fantôme de référence est mis en file d'attente alors qu'il n'est plus récupérable, qui sont généralement de la même chose). Une utilisation courante est:
Il est également finalize(), qui ressemble à un destructeur, mais ne se comporte pas comme un. Il n'est généralement pas une bonne option.
Je suis désolé si cela s'éloigne du sujet principal, mais java.util.Minuterie (SE6) documentation dit:
"Après le dernier live de référence à un objet Timer s'en va et toutes les tâches en suspens ont terminé l'exécution, la minuterie de l'exécution de la tâche thread se termine normalement (et devient l'objet de la collecte des ordures). Toutefois, cela peut prendre arbitrairement long à se produire. Par défaut, l'exécution de la tâche fil ne fonctionne pas comme un fil de démon, de sorte qu'il est capable de garder une demande de résiliation. Si l'appelant veut mettre fin à un timer de l'exécution de la tâche fil rapidement, l'appelant doit invoquer la minuterie d'annulation de la méthode..."
Je voudrais lancer un appel d'annuler la classe possédant la Minuterie de perdre sa dernière référence(ou immeditalesky avant). Ici, fiable destructeur pourrait le faire pour moi. Les commentaires ci-dessus indiquent que, finalement, est un mauvais choix, mais est-il une solution élégante? Cette entreprise de "...capable de garder une demande de résiliation de..." n'est pas attrayant.
Timer
instance est inaccessible, vous n'avez pas besoin d'appelercancel
sur elle, que c'est ce que le texte cité est tout au sujet. Vous devriez appelercancel
sur elle si vous voulez précédente nettoyage, c'est à dire lorsque l'objet est toujours accessible.La
finalize()
fonction est le destructeur.Cependant, il ne devrait pas être utilisé normalement parce qu'il est invoqué après la GC et vous ne pouvez pas dire quand cela va se produire (si jamais).
En outre, il prend plus d'une GC pour désallouer les objets qui ont
finalize()
.Vous devriez essayer de nettoyer dans la logique des lieux de votre code à l'aide de la
try{...} finally{...}
états!Je suis d'accord avec la plupart des réponses.
Vous ne devriez pas dépendre entièrement sur
finalize
ouShutdownHook
finaliser
La JVM n'est pas garantie lors de cette
finalize()
méthode sera invoquée.finalize()
est appelée qu'une seule fois par GC fil. Si un objet se rétablit partir de la finalisation de la méthode, puisfinalize
ne sera pas appelé à nouveau.Dans votre application, vous pouvez avoir des objets en direct, sur laquelle la collecte des ordures n'est jamais invoquée.
Tout
Exception
qui est jeté par la finalisation de la méthode est ignoré par le GC filSystem.runFinalization(true)
etRuntime.getRuntime().runFinalization(true)
méthodes pour augmenter la probabilité de l'invocation d'finalize()
méthode mais maintenant, ces deux méthodes ont été dépréciées. Ces méthodes sont très dangereux à cause du manque de fil de sécurité et blocage possible de la création.shutdownHooks
La Java virtual machine s'arrête en réponse à deux types d'événements:
System.exit
) la méthode est invoquée, ouArrêt crochets doit aussi terminer leur travail rapidement. Lorsqu'un programme appelle la sortie de l'espoir, c'est que la machine virtuelle sera rapidement arrêté et de sortie.
Mais même la documentation d'Oracle cité que
Cela se produit lorsque la machine virtuelle est mis fin à l'externe, par exemple avec la
SIGKILL
signal sur Unix ou laTerminateProcess
appel sur Microsoft Windows. La machine virtuelle peut également annuler si une méthode native va de travers, par exemple, pour corrompre les structures de données internes ou de tenter d'accéder inexistant de la mémoire. Si la machine virtuelle abandonne alors qu'aucune garantie ne peut être faite quant à savoir si ou non un arrêt de crochets sera exécuté.Conclusion : utilisation
try{} catch{} finally{}
blocs de façon appropriée et de libérer les ressources critiques dansfinally(}
bloc. Au cours de la libération des ressources enfinally{}
bloc catchException
etThrowable
.Si c'est juste de la mémoire vous inquiète, n'en ont pas. Simplement confiance à la GC, il fait un travail décent. J'ai effectivement vu quelque chose à ce sujet étant tellement efficace qu'il pourrait être mieux pour les performances de créer des tas de petits objets que d'utiliser des tableaux de grande taille dans certains cas.
Peut-être vous pouvez utiliser un bloc try ... finally pour finaliser l'objet dans le flux de contrôle à laquelle vous êtes à l'aide de l'objet. Bien sûr, il ne se produit pas automatiquement, mais ni la destruction en C++. Vous voyez souvent de clôture de ressources dans le bloc finally.
Il y a un @Nettoyage annotation à Lombok qui la plupart du temps ressemble à C++ destructeurs:
Lors du traitement de celle-ci (au moment de la compilation), Lombok accessoires adaptés
try-finally
bloc de sorte queresource.close()
est appelé, lors de l'exécution des feuilles de la portée de la variable. Vous pouvez également spécifier explicitement une autre méthode pour la libération de la ressource, par exempleresource.dispose()
:@Cleanup
plus-avec-des ressources?@Cleanup
L'équivalent le plus proche à un destructeur en Java est la finalize() méthode. La grande différence avec les traditionnels destructeur est que vous ne pouvez pas être sûr que quand il va être dit, parce que c'est la responsabilité du garbage collector. Je recommanderais fortement de lire attentivement cette avant de l'utiliser, étant donné que votre typique RAIA modèles pour les descripteurs de fichiers et ainsi de suite ne fonctionne pas de manière fiable avec finalize().
Si vous êtes à la rédaction d'un Applet Java, vous pouvez remplacer l'Applet "destroy()" la méthode. Il est...
Évidemment pas ce que vous voulez, mais peut-être ce que d'autres personnes sont à la recherche pour.
Bien qu'il y ait eu beaucoup de progrès en Java GC de la technologie, vous avez encore besoin d'être conscient de vos références. De nombreux cas d'anodin motifs de référence qui sont en fait les nids de rats sous le capot viennent à l'esprit.
À partir de votre post, il ne sonne pas comme vous essayez de mettre en œuvre une méthode de réinitialisation pour le but de la réutilisation d'un objet (vrai?). Sont vos objets de tenir n'importe quel autre type de ressources qui doivent être nettoyées (c'est à dire, les ruisseaux qui doit être fermé, collectif ou d'objets empruntés doivent être retournés)? Si la seule chose que vous êtes inquiet au sujet de la mémoire est dealloc puis-je revenir sur ma structure de l'objet et de tenter de vérifier que mes objets sont autonomes structures qui vont être nettoyé à la GC temps.
Il suffit de penser au sujet de la question d'origine... ce qui, je pense que nous pouvons conclure à partir de tous les autres appris réponses, et aussi de Bloch est essentiel Efficace Java, point 7, "Éviter les finaliseurs", cherche la solution à une question légitime dans une manière qui est inapproprié pour le langage Java...:
... n'est-ce pas assez évident que la meilleure solution pour faire ce que l'OP veut vraiment être de garder tous vos objets qui doivent être remis à zéro dans une sorte de "parc pour enfants", à laquelle tous les autres non-programmable objets ont des références seulement à travers une sorte d'accesseur objet...
Et puis quand vous avez besoin de "reset" vous débranchez le parc existant et en faire une nouvelle: tout le web des objets dans le parc est jeté à la dérive, pour ne jamais revenir, et un jour pour être recueillis par le GC.
Si l'un de ces objets sont
Closeable
(ou pas, mais avoir unclose
méthode), vous pouvez les mettre dans unBag
dans le parc comme ils sont créés (et éventuellement ouvert), et le dernier acte de l'accesseur avant de couper le parc serait de passer par tous lesCloseables
de les fermer... ?Le code serait probablement ressembler à quelque chose comme ceci:
closeCloseables
serait probablement un blocage de la méthode, impliquant probablement un loquet (par exempleCountdownLatch
), à traiter (et d'attendre que échéant) de touteRunnables
/Callables
dans tous les threads spécifiques à laPlaypen
être terminé, comme il convient, en particulier dans le JavaFX fil.Il n'est pas exactement le destructeur de la classe en Java, la classe détruit en java automatiquement par le garbage collector . mais vous pouvez le faire à l'aide ci-dessous mais ce n'est pas exactement la même chose :
finalize()
Il y avait une question qui a engendré une discussion en profondeur de finaliser , de sorte que vous devriez obtenir plus de profondeur si nécessaire...
Beaucoup de grandes réponses ici, mais il ya quelques informations supplémentaires au sujet de pourquoi vous devriez éviter d'utiliser des finalize().
Si la JVM est arrêté à cause de
System.exit()
ouRuntime.getRuntime().exit()
, finaliseurs ne sera pas exécuté par défaut. De Javadoc pour l'Exécution.exit():Vous pouvez appeler
System.runFinalization()
mais il ne fait que "meilleur effort de terminer tous en circulation le nombre de cas réglés" – pas une garantie.Il y a un
System.runFinalizersOnExit()
méthode, mais ne l'utilisez pas, il n'est pas sécuritaire, obsolète depuis longtemps.J'ai utilisé pour traiter principalement avec C++ et c'est ce que me conduire à la recherche d'un destructeur aussi. Je suis à l'aide de JAVA beaucoup maintenant. Ce que j'ai fait, et c'est peut-être pas le meilleur des cas pour tout le monde, mais j'ai mis en place mon propre destructeur par mettre à zéro toutes les valeurs à 0 ou là par défaut par le biais d'une fonction.
Exemple:
Idéalement, cela ne fonctionne pas pour toutes les situations, mais où il y a des variables globales, il va travailler aussi longtemps que vous n'avez pas une tonne d'eux.
Je sais que je ne suis pas le meilleur programmeur Java, mais il semble fonctionner pour moi.