Force java для выпуска всех файловых замков/дескрипторов в Java

Мое приложение Java (которое довольно немного кода) выполняет множество операций с файлами. В какой-то момент в моем приложении мне нужно переместить файл из одного места в другое, и для этого я использую метод Files.move из JDK7.

Когда я пытаюсь это сделать, я получаю сообщение об ошибке, указывающее, что файл используется. Я знаю, что это часть моего кода, которая блокирует этот ресурс.

Как заставить мое приложение Java освободить все блокировки до вызова функции, которая перемещает/переименовывает мой файл?

Если это невозможно, есть ли простой способ проверить, какая часть моего кода блокирует файл? Трудясь через всю мою кодовую базу, чтобы найти закрытые файловые дескрипторы, был бы кошмар с учетом количества кода.

Спасибо

Ответ 1

С помощью отладчика вы можете увидеть все экземпляры объектов, которые у вас есть в памяти (в Netbeans это будет Windows | Отладка | Загруженные классы, а затем щелкните правой кнопкой мыши → Показать экземпляры). Затем вы можете увидеть все экземпляры FileInputStream/FileOutputStream, которые у вас есть, и определить те, которые указывают на файл, который вы пытаетесь переместить. После того, как вы нашли ссылку на свой файл, вы можете увидеть, кто все еще держит ссылку.

Если никто не держит ссылку на файл, возможно, экземпляр был отброшен без вызова close(), и файл будет нормально выпущен только после сбора мусора. Это делает предыдущий подход бесполезным, так как я думаю, что отладчик автоматически мусор собирал эти потоки для вас. Возможно, вы могли бы поставить условную точку останова внутри конструктора потока и сказать ей прекратить только тогда, когда параметр конструктора ссылается на ваш файл.

Если вы не можете найти что-либо, в крайнем случае вы можете попытаться поставить пару вызовов System.gc() перед операцией перемещения и посмотреть, есть ли у вас улучшения. Очевидно, что это будет только быстро и грязно, чтобы дать вам некоторое время, пока не найдете актуальную проблему.

Ответ 2

Любое решение, отличное от закрывающих потоков (предпочтительно в блоке try.. finally), будет задачей botch и будет рисковать сделать вещи более неустойчивыми, чем они есть.

Я знаю, что это боль, чтобы исправить это в большой базе кода. Если вы не хотите перетаскивать свой код, FindBugs хорош в поиске незакрытых потоков. Там есть плагин Eclipse, и вы можете отфильтровать найденные вами ошибки только тем, кого вас интересуют.

Ответ 3

Объект File() не блокирует файл, но FileStream (FileInputStream/FileOutputStream) блокирует его. Таким образом, вы должны написать HelperClass (например, Singleton) для ваших потоков, которые регистрируют все потоки.

Но заметьте, если у вас есть утечка в коде, гораздо лучше исправить ошибку, чем закрыть все файлы.