12
votes

Les entrées / sorties se ferment-elles sur la destruction?

fait des intrigions et des sorties de sortie à Java Fermer () sur la destruction? Je comprends parfaitement que cela peut être une mauvaise forme (ESP dans le monde C et C ++), mais je suis curieux.

En outre, supposons que j'ai le code suivant: xxx > Est-ce que la fileDinPutStream sans nom est hors de portée après p.load () et est donc détruite, un peu comme des règles de scopage C ++? J'ai essayé de chercher une lunette variable anonyme pour Java sur Google, mais cela n'a pas présenté ce que je pensais que ce serait.

Merci.


2 commentaires

Merci tout pour l'aide!


Notez que le ESSAYER avec des ressources en JAVA 7 ou plus ferait la fixation de ce problème une opération relativement simple (nécessitant simplement une affectation de variable supplémentaire et bien sûr le essayez ). Notez également que le code ci-dessus générerait un avertissement (à propos de la fermeture manquante) dans mon environnement Eclipse.


5 Réponses :


5
votes

Non, il n'y a pas de destructeurs en Java. Il peut y avoir d'autres références à l'objet, même après une référence particulière à celle-ci dépasse de la portée (ou est modifiée). Si l'objet n'est plus accessible, le flux peut avoir son finaliseur appelé un jour plus tard, ce qui fermera le flux.

properties.load est particulier dans la fermeture du flux qui est transmis. Edition: Propriétés.LoadFromXML est la méthode spéciale que j'appartiens avoir réfléchi il y a cinq ans environ cinq ans. (API DOC devrait probablement dire avant plutôt qu'après.) Merci @tzimnoch.


3 commentaires

Il n'y a pas de destructeurs, mais il y a des finaliseurs. Et les finaliseurs de la majorité des classes d'introuve / de sortie de Java.io pour fermer le flux.


@ CHSSPLY76: Droite, mais il n'y a aucune garantie whatsoever à propos de quand, ou même si les derniers finis seront appelés. Rien.


doc.oracle .Com / Javase / 7 / Docs / API / Java / ... "Le flux spécifié reste ouvert après que cette méthode revienne."



3
votes

La variable est hors de portée et est donc détruite. Mais en Java, il y a une très grande distinction entre une variable et l'objet que la variable pointe vers .

L'objet pointé sur n'est pas détruit simplement lorsque la variable est hors de portée. L'objet n'est détruit que lorsque le moteur Java Runtime décide qu'il a l'impression de se déplacer pour détruire des objets qui ne sont pas signalés par des variables de la portée.


0 commentaires

18
votes

première réponse: il n'y a pas de "destruction" (dans le sens de la C ++) en Java. Il n'y a que le collecteur des ordures, qui peut ne pas se réveiller et ne pas faire son travail quand il voit un objet prêt à être collecté. GC en Java est généralement indigne de confiance.

Seconde réponse: Parfois, oui, parfois non, mais ne valez pas la peine de prendre un risque sur. De Elliote Rusty Harold's Java Io :

Tous les flux ne doivent pas nécessairement être des flux de sortie de la matrice fermée NE PAS Besoin d'être fermé, par exemple. Cependant, des flux associés à des fichiers et les connexions réseau doivent toujours être fermées lorsque vous avez terminé avec elles. Par exemple, si vous ouvrez un fichier pour écrire et négliger de le fermer lorsque Vous êtes à travers, puis d'autres processus peuvent être bloqués de la lecture ou écrire dans ce fichier.

Selon Harold, il en va de même pour les flux d'entrée ou de sortie. Il y a quelques exceptions près (il note System.in), mais en général, vous prenez un risque si vous ne fermez pas les flux de fichiers lorsque vous avez terminé. Et fermez-les dans un bloc enfin pour vous assurer qu'ils sont fermés, même si une exception est lancée.


0 commentaires

6
votes

J'avais l'habitude de supposer que les flux seraient fermés automatiquement via la collecte des ordures, mais des preuves anecdotiques indiquent que l'échec de la fermeture manuelle entraîne des résultats dans une fuite de ressources. Vous voudrez faire quelque chose comme ça à la place:

InputStream stream = null;

try {
  stream = new FileInputStream("bar.txt");
  Properties p = new Properties();
  p.load(stream);
}
catch(Exception e) {
  // error handling
}
finally {
  closeQuietly(stream);
}


0 commentaires

3
votes

La réponse courte est "Peut-être, mais ne parie pas dessus!".

Quelque part dans la pile de classes qui implémentent FileInputStream est une classe qui possède un qui fermera efficacement le flux (et libérera la ressource) lorsqu'il est exécuté.

Le problème est qu'il n'ya aucune garantie que le finaliseur sera jamais exécuté. Citant de la JLS (section 12.6):

Le langage de programmation Java ne fait pas Spécifiez combien de temps un finaliseur sera invoqué, sauf pour dire que ça va arriver avant le stockage pour le objet est réutilisé.

Ceci fait la finalisation du flux problématique:

  1. Si votre objet de flux ne devient jamais des ordures, il ne sera jamais finalisé.
  2. Si votre objet de flux est tenu en occupation, cela peut prendre beaucoup de temps avant que la poubelle soit collectée et finalisée.
  3. Le JVM peut avoir besoin d'effectuer un cycle de GC supplémentaire après l'identification de l'objet comme inaccessible avant que le finaliseur soit exécuté. Ceci est certainement permis par les JLS!
  4. Il est techniquement légal pour une JVM de ne jamais, jamais pour exécuter des finaliseurs, à condition qu'il ne réduit jamais le magasin d'objets avec des finaliseurs. (Je ne suis au courant d'aucune JVM de qualité de production qui prennent cette ligne, mais vous ne savez jamais ...)

3 commentaires

Je penserais que si le JVM a été faible en ressources, il finaliserait les objets de fichiers fermés. (Ne pas tolérer ne pas nettoyer après vous-même.)


Vous pourriez penser que ... mais Afaik, à court de descripteurs de fichier ne déclenche pas une analyse de GC qui détecterait que d'autres objets de flux sont (hypothétiquement) maintenant finalisables.


@Mike Jones: Non, ce n'est pas le cas. Cela peut être pratiquement prouvé. Mettre à basse mémoire peut déclencher la collection de déchets (il est même mandaté de faire du mieux avant de lancer un OutofMemoryError ), mais GC est pas identique à la finalisation. La collection de déchets entraînera des objets avec des finaliseurs Enqueuser pour une finalisation ultérieure, mais il est complètement non défini lorsque la finalisation se produira. Donc, lors de l'exécution de descripteurs de fichier (ou de toute autre ressource non mémoire) ne déclenche pas de GC de toute façon (comme Stephen désigné déjà), même si GC est déclenché, elle ne force pas la finalisation.