Я столкнулся с подобной проблемой приблизительно год назад. В нашем случае наши разработчики фронтэнда были все знакомы с JSP, и я действительно не хотел бросать другой механизм шаблонной обработки в соединение. Я хотел что-то, что полагалось на процессор JSP контейнера сервлета для генерации почтового содержания для меня.
Это довольно просто:
HttpServletResponse
и ServletOutputStream
, который получает содержание, записанное контейнером сервлета, и превращает его в Строку и полагался RequestDispatcher.include(...)
для выполнения "запроса" к шаблону JSP (я также записал пользовательское HttpServletRequest
для изоляции исходного запроса от мутации). Первый ответ: в Java не существует такого понятия, как «разрушение» (в смысле C ++). Есть только сборщик мусора, который может или не может просыпаться и выполнять свою работу, когда видит объект, готовый к сбору. GC в Java вообще ненадежен.
Второй ответ: иногда да, иногда нет, но рисковать не стоит. Из Эллиота Расти Гарольда Java IO :
Не все потоки нужно закрывать - потоки вывода байтового массива не нужно закрыть, например. Однако потоки, связанные с файлами и сетевые соединения всегда должны быть закрыты, когда вы закончите с ними. Например, если вы открываете файл для записи и не закрываете его, когда вы прошли, тогда другие процессы могут быть заблокированы для чтения или запись в этот файл.
По словам Гарольда, то же самое касается входных и выходных потоков. Есть некоторые исключения (он отмечает System.in), но в целом вы рискуете, если не закроете файловые потоки, когда закончите. И закройте их в блоке finally, чтобы убедиться, что они закрываются даже в случае возникновения исключения.
Раньше я предполагал, что потоки в конечном итоге будут автоматически закрыты через сборку мусора, но неофициальные данные показывают, что неспособность закрыть их вручную приводит к утечке ресурсов. Вместо этого вы захотите сделать что-то вроде этого:
InputStream stream = null;
try {
stream = new FileInputStream("bar.txt");
Properties p = new Properties();
p.load(stream);
}
catch(Exception e) {
// error handling
}
finally {
closeQuietly(stream);
}
closeQuietly ()
- это метод для IOUtils
в библиотеке Apache commons-io.
Переменная выходит за пределы области видимости и поэтому уничтожается. Но в Java существует очень большое различие между переменной и объектом , на который переменная указывает на .
Объект указывает на не уничтожается только тогда, когда переменная выходит за пределы области видимости. Объект уничтожается только в том случае, если механизм выполнения Java решает, что он хочет приступить к уничтожению объектов, на которые не указывают никакие переменные в области видимости.
Нет, в Java нет деструкторов. Могут быть и другие ссылки на объект, даже после того, как одна конкретная ссылка на него выходит за рамки (или изменяется). Если объект больше недоступен, через некоторое время может быть вызван финализатор потока, который закроет поток.
Изменить: Свойство Properties.load
характерно тем, что закрывает переданный ему поток. Properties.loadFromXML
- это особый метод, о котором я, кажется, думал лет пять назад или около того. (Документ API, вероятно, должен сказать «до», а не «после».) Спасибо @tzimnoch.
Короткий ответ: «Возможно, но не делайте этого!».
Где-то в стеке классов, реализующих FileInputStream, есть класс, имеющий финализатор
, который эффективно закроет поток (и освободит ресурс) при его запуске.
Проблема в том, что нет гарантии, что финализатор когда-либо запустится. Цитата из JLS (раздел 12.6):
Язык программирования Java не поддерживает укажите, как скоро будет финализатор вызывается, за исключением того, что он будет происходит перед хранением для объект повторно используется.
Это делает завершение потока проблематичным: