Если я правильно понял вопрос, вы беспокоитесь о том, что не должным образом очистите его, если JVM будет отключен неконтролируемым образом.
Хотя это общая проблема, в вашем конкретном случае я думаю, что не о чем беспокоиться. Вы только открываете свои файлы для чтения, поэтому нет постоянного состояния, которое может испортить ваше приложение (как я понимаю, с другой стороны TCP-соединения можно корректно обрабатывать разъединения). Открываемый файл - это своеобразное состояние, которое является внутренним для приложения. Если приложение убито, операционная система выполняет очистку всех блокировок или любых структур данных, которые он может использовать внутри, для обработки операций над этим файлом. Это означает, что в ядре ОС не останется «мусора», и хотя он не является ни элегантным, ни рекомендуемым способом очистки, он просто работает (конечно, использовать это только для чрезвычайных ситуаций, а не как обычный способ обработки вещей). Убийство вашего приложения автоматически закрывает открытые файлы и не должно приводить файлы в какое-либо несогласованное состояние.
Конечно, если приложение убито, оно не завершит выполнение каких-либо операций. Это может привести к несогласованному состоянию на уровне приложения или другим проблемам с некоторыми видами логики приложения, но все равно не может повредить какие-либо нововведения на уровне ОС (при условии, что ОС не глючит). Вы можете потерять данные или разорвать состояние своего приложения, но не сможете разбить файловую систему или данные в ядре.
Таким образом, вы можете столкнуться с проблемами, если вы убьете приложение, в котором у вас есть операция в стиле транзакции (которую вы хотите полностью или полностью выполнить, но никакое промежуточное состояние никогда не должно становиться видимым для внешнего мира). Например, если бы у вас был файл, и вам нужно было заменить его более новой версией. Если вы сначала усекаете старый файл, а затем записываете в него новое содержимое (что является очевидным способом сделать это), если ваше приложение убито после обрезания файла, но перед написанием нового содержимого у вас проблемы. Однако, чтобы спровоцировать такие риски, вам нужно изменить состояние, то есть написать что-то. Если вы только читаете материал, вы почти наверняка будете в безопасности.
Если вы столкнулись с таким случаем, вы можете воспользоваться несколькими путями. Один пытается сделать приложение пуленепробиваемым и гарантировать, что он всегда хорошо очищается. На практике это очень сложно. Вы можете добавить крючки завершения к Java-приложению, которое будет выполняться при закрытии приложения, но оно работает только для управляемого выключения (например, обычного kill
(SIGTERM) в Linux). Но это не защитит вас от приложения, которое будет насильно убито администратором (kill -9
на Linux), OOM-killer (также Linux) и т. Д. Конечно, другие операционные системы имеют эквиваленты этих ситуаций или другие случаи, когда приложение закрывается таким образом, что он не может управлять. Если вы не пишете приложение реального времени, работающее в контролируемой аппаратной и программной среде, практически невозможно предотвратить все попытки приложения принудительно прекратить работу и предотвратить выполнение его процедур очистки.
Таким образом, разумный компромисс часто принимает только простые меры предосторожности в приложении (например, крюки отключения), но следует помнить, что вы не можете предотвратить все и, следовательно, сделать ручную очистку возможной и легкой. Например, решением для перезаписи файла было бы разделение операции на первое перемещение старого файла на новое имя для сохранения в качестве резервной копии (эта операция обычно является атомарной на уровне ОС и поэтому безопасна), а затем записывая новое содержимое файла для старого имени, а затем после проверки того, что новый файл был правильно написан, удалите резервную копию. Таким образом, если приложение убито между операциями, существует простая процедура очистки: перенос файла резервной копии на исходное имя и, таким образом, возврат к более старому, но согласованному состоянию. Это может быть выполнено вручную (но должно быть документировано), или вы можете добавить скрипт очистки или специальную команду «очистка» для вашего приложения, чтобы сделать эту операцию простой, видимой и удалить возможность человеческой ошибки во время процедуры.Предполагая, что ваше приложение убито редко, это обычно более эффективно, чем тратить много времени на попытку сделать приложение пуленепробиваемым только для того, чтобы понять, что это действительно невозможно. Обмануть отказ часто лучше, чем пытаться его предотвратить (не только в программировании).
Вы все еще можете сгореть на OS и аппаратном уровне, но это действительно сложно предотвратить с помощью аппаратного обеспечения и ОС. Даже если ваше приложение увидит новый файл в правильном месте, он, возможно, не был физически записан на диск, и если он будет находиться только в кеше, он не потеряется, если ваше приложение будет убито, но потеряется, если кто-то вытащит мощность подключите машину. Но дело в таком провале - совершенно другая история.
Короче говоря, в вашем конкретном случае, когда вы читаете только файлы, ОС должна выполнять всю очистку, если ваше приложение убито, а в других случаях некоторые советы упоминаются выше.
Возможно, я не был чист: потоки, на которые я ссылаюсь, это FileInputStream/FileOutputStreams. TCP-соединение, с другой стороны, постоянно хранится в сети (если оно не выполняется, происходит повторное подключение). –
Я не уверен, что понял ваш вопрос. Очищая поток, вы хотите удалить частично перенесенные файлы? – WilQu
Нет, я имею в виду вызов close() в FileInputStream/FileOutputStream разных файлов. Я попытаюсь сделать что-то, чтобы сделать этот вопрос менее загадочным. Через несколько минут я вернусь с редактированием. –