2012-07-20 12 views
11

La mia applicazione Java (che è un bel po 'di codice) esegue molte operazioni sui file. A un certo punto nella mia applicazione, ho bisogno di spostare un file da una posizione a un'altra e per questo sto usando il metodo Files.move da JDK7.Forza java per rilasciare tutti i blocchi/gli handle di file in Java

Quando provo a farlo, viene visualizzato un errore indicante che il file è in uso. So per certo che è una parte del mio codice che sta bloccando questa risorsa.

Come impongo alla mia applicazione Java di rilasciare tutti i blocchi prima di chiamare la funzione che sposta/rinomina il mio file?

Se questo non è possibile, c'è un modo semplice per verificare quale parte del mio codice sta bloccando il file? Trudging attraverso la mia intera base di codice per trovare handle di file non chiusi sarebbe un incubo considerando la quantità di codice che esiste.

Grazie

+0

forse di aiuto: http://stackoverflow.com/questions/4179145/release-java-file-lock-in-windows – Chris

risposta

3

Con l'aiuto di un debugger è possibile vedere tutte le istanze di oggetti che avete in memoria (in Netbeans questo sarebbe di Windows | debug | classi caricate, e quindi fare clic destro -> Mostra istanze). È quindi possibile visualizzare tutte le istanze di FileInputStream/FileOutputStream e identificare quelle che puntano al file che si sta tentando di spostare. Una volta trovato un riferimento al tuo file, puoi vedere chi sta ancora conservando il riferimento.

Se non c'è nessuno in possesso di un riferimento al file, è possibile che l'istanza sia stata scartata senza chiamare close() e che il file venga normalmente rilasciato solo dopo una garbage collection. Questo rende l'approccio precedente inutile, dal momento che penso che il debugger automaticamente raccoglierebbe automaticamente quei flussi per te. Forse potresti inserire un breakpoint condizionale all'interno del costruttore di stream e dirgli di fermarsi solo quando il parametro del costruttore si riferisce al tuo file.

Se non riesci a trovare nulla, come ultima risorsa puoi provare a mettere un paio di chiamate System.gc() prima della tua operazione di spostamento e vedere se hai qualche miglioramento. Chiaramente questa sarebbe solo una soluzione rapida e sporca, per darti un po 'di tempo prima di trovare il vero problema.

+0

In realtà le istanze di 'File' non bloccano i file. Un 'File' è solo una rappresentazione di un nome di percorso di file o directory. 'System.gc()' non chiude mai nessun flusso di file aperto. –

+0

Hai ragione su 'File'. Ho corretto la risposta per fare riferimento a 'FileInputStream' /' FileOutputStream'. Mantengo comunque il mio consiglio su 'System.gc()': le due classi hanno un metodo 'finalize' che chiude lo stream, quindi se hai appena scartato l'oggetto senza chiamare close, una garbage collection potrebbe aiutarti. – Flavio

+0

Hai ragione riguardo finalize() nei flussi di file, quindi hai ragione potrebbe essere d'aiuto. È però traballante! Non è possibile controllare quando avviene la garbage collection né ciò che viene raccolto, quindi non vorrai fare affidamento su comportamenti come questo in produzione. –

3

Qualsiasi soluzione diversa dalla chiusura dei flussi correttamente (preferibilmente all'interno di un blocco try.. finally) sarà un lavoro di botch e rischierà di rendere le cose più instabili di quanto non lo siano già.

So che è un problema risolvere questo problema in un grande codebase. Se non vuoi navigare attraverso il tuo codice, FindBugs è in grado di localizzare i flussi non chiusi. C'è un plugin Eclipse e puoi filtrare i bug che trova solo per quelli che ti interessano.

3

L'oggetto File() non blocca un file, ma un FileStream (FileInputStream/FileOutputStream) lo blocca. Quindi devi scrivere un HelperClass (ad esempio Singleton) per i tuoi stream, che registra tutti gli stream.

Tuttavia, se si ha una perdita nel codice, è molto meglio correggere l'errore che chiudere tutti i file.