Потоки должны быть явно закрыты с использованием шаблона, показанного в ответе @ erickson.Полагаться на завершение закрытия потоков для вас - это очень плохая идея :
Вызов System.gc()
стоит дорого, тем более что (если он что-то делает) с большой вероятностьюзапустить полную сборку мусора.Это приведет к отслеживанию каждой ссылки в каждом достижимом объекте в вашей куче.
Если вы прочитаете javadocs для System.gc()
, вы увидите, что это только«подсказка» JVM для запуска GC.JVM может игнорировать подсказку ... что приводит нас к следующей проблеме.
Если вы не запустите GC явно, это может занять много времени, пока GCпробеги.И даже тогда нет никакой гарантии, что финализаторы будут запущены немедленно.
В то же время:
- все открытые файлы остаются открытыми, что может помешать другим приложениям использоватьих
- все неписанные данные в потоках остаются неписанными
- ваше java-приложение может даже столкнуться с проблемами при открытии других потоков из-за отсутствия слотов файлового дескриптора.
И есть еще одна проблема с использованием финализации для обработки выходных потоков.Если в потоке есть незаполненные данные, когда он завершается, класс потока вывода попытается сбросить их.Но все это происходит во внутреннем потоке JVM, а не в одном из потоков вашего приложения.Поэтому, если сбой сброса (например, из-за переполнения файловой системы), ваше приложение не сможет перехватить полученное исключение и, следовательно, не сможет сообщить об этом ... или сделать что-нибудь для восстановления.
EDIT
Возвращаясь к исходному вопросу, оказывается, что класс BufferedOutputStream не переопределяет метод Object.finalize()
по умолчанию.Это означает, что BufferedOutputStrean вообще не сбрасывается при сборке мусора.Любые неписанные данные в буфере будут потеряны.
Это еще одна причина явного закрытия ваших потоков.В самом деле, в данном конкретном случае вызов System.gc()
- это не просто плохая практика;также вероятно может привести к потере данных.