Path: csiph.com!news.mixmin.net!newsreader4.netcologne.de!news.netcologne.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Andreas Karrer Newsgroups: de.comp.lang.java Subject: Re: Files.move() scheitert, wirft aber keine Ausnahme Date: 1 Feb 2016 14:35:37 GMT Lines: 57 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: individual.net cogf1+GKp6GiYDa6dUdt/g3bP3oQgI6RuUx6CqmxSE26ysGmQq Cancel-Lock: sha1:2NdM8Sjpj9QPYmNGGdr9orJoyyg= User-Agent: slrn/1.0.2 (Linux) Xref: csiph.com de.comp.lang.java:12908 * Christoph Schneegans : > Hallo allerseits! > > In meiner Applikation gibt es folgenden Aufruf: > > java.nio.Files.move(source, target, > java.nio.file.StandardCopyOption.REPLACE_EXISTING); > > Nun ist offenbar – bislang einmalig – folgendes passiert: > > • Die vorhandene, nicht leere Datei target wurde geleert bzw. durch eine > 0 Bytes großen Datei ersetzt. > • source ist noch unverändert vorhanden (und ist nicht leer, sondern ca. > 1,5 MB groß). > • Es gab _keine_ Ausnahme. > > Die Applikation wird unter CentOS 5.11 ausgeführt. source und target > sind Pfade im lokalen Dateisystem. Dieselbe Operation hat zuvor in fast > einer Million Fällen fehlerfrei funktioniert. Das sollte nicht passieren können. Files.move() geht bei Files auf einem lokalen Unix/Linux-Filesystem so vor: - target wird gelöscht (weil REPLACE_EXISTING) - rename(source, target) (der System call rename(2)) - wenn rename erfolgreich war, dann ist die Sache gegessen - EISIR (target ist ein Directory) wird irgendwie abgehandelt, interessiert hier nicht - beim Fehler EXDEV (source und target auf unterschiedlichen Filesystemen): - das File wird Block für Block kopiert - die Metainformationen (mode, owner etc) werden kopiert - source wird gelöscht. Wenn source und target zwei Files auf dem gleichen lokalen Fileystem sind, dann ist der Systemcall rename(2) unter CentOS atomar, d.h. das beschriebene Verhalten kann nicht auftreten. Es handelt sich im vorliegenden Fall also offenbar um Files auf unterschiedlichen Filesystemen (oder auch dem gleichen Filesystem, das an unterschiedlichen Mountpoints eingehängt ist). Dieser Code ist nicht atomar, d.h. er kann (z.B. durch ein Signal, Disk voll, Hardwarefehler oder so etwas) mittendrin unterbrochen werden. Im beschriebenen Fall wäre das dann passiert, als das target-File bereits zum Schreiben geöffnet war, aber noch keine Daten kopiert wurden. Das sollte aber immer eine IOException zur Folge haben. http://cr.openjdk.java.net/~littlee/7129029/webrev.00/src/solaris/classes/sun/nio/fs/UnixCopyFile.java.html Es ist natürlich auch denkbar, dass der vorgefundene Zustand (source intakt, target überschrieben und 0 Bytes gross) gar nicht durch Files.move() ausgelöst wurde, sondern durch irgendwelchen anderen Code in der Applikation. - Andi