#java #garbage-collection #dispose
#java #сбор мусора #утилизировать
Вопрос:
C # поддерживает одноразовый шаблон для детерминированной сборки мусора с использованием шаблона dispose .
Существует ли такой шаблон для Java?
В Java 7 есть autoclosable
, который вы можете использовать с блоками try finally для вызова close
метода.
Как насчет версий до 7?
Существует ли одноразовый шаблон (детерминированная сборка мусора) для Java 5 или 6?
Комментарии:
1. Боюсь, нет, вы должны сделать это вручную.
2. Автоматическое закрытие не влияет на сборку мусора. Что он делает, так это обеспечивает правильную очистку ресурсов. Вы уверены, что шаблон C # оказывает какое-либо влияние на GC?
3. Я просто хотел отметить, что ни C #,
using
ни Java 7try
с использованием шаблонов ресурсов не предлагают детерминированную сборку мусора . Они предлагают детерминированный контроль ресурсов . Я знаю, что я педантичен в этом, но это важное отличие.4. @PeterLawrey похоже, что мы разместили одно и то же. C # такой же, как у Java; по умолчанию нет реального влияния на GC, хотя некоторые шаблоны (в частности, собственный шаблон, предложенный Microsoft) рекомендуют подавлять финализацию — первый шаг в сборке мусора. Несмотря на это, память объекта не восстанавливается немедленно.
Ответ №1:
Ближайший к Java 7 — это просто «ручные» блоки try / finally:
FileInputStream input = new FileInputStream(...);
try {
// Use input
} finally {
input.close();
}
Это using
утверждение было одной из самых приятных вещей, которые я нашел в C #, когда я впервые начал использовать C # 1.0 на фоне Java. Приятно наконец увидеть это в Java 7 🙂
Вы также должны учитывать Closeables
в Guava — это позволяет вам не беспокоиться о том, является ли ссылка нулевой (точно так же, как using
это делает оператор), и, возможно, «регистрирует и проглатывает» исключения, создаваемые при закрытии, чтобы избежать эффективного «перезаписывания» любого такого исключения исключением, генерируемым из блока try.
Комментарии:
1. Разве это не может привести к утечке ресурса? Не было бы лучше инициализировать
input
null
снаружиtry
и построитьFileInputStream
внутриtry
. Затемfinally
проверьте наличие неnull
экземпляра и закройте его. (Я почти уверен, что его нужно инициализироватьnull
внеtry
, потому что в противном случае назначение не может быть гарантировано.)2. @NoelWidmer: если между назначением и вводом блока может возникнуть асинхронное исключение
try
, то такое же исключение, предположительно, может возникнуть после завершения конструктора, но до того, как результирующая ссылка будет присвоенаinput
переменной. Но, по крайней мере, в Java я не считаю, что это проблема.3. @JonSkeet Ты прав. (Хотя я не знаю, может ли асинхронность быть проблемой в Java)
4. @Noel: Под асинхронными исключениями я подразумеваю исключения, которые могут быть сгенерированы в совершенно произвольных точках.
5. @JonSkeet я знаю, что ты имел в виду. Эти мерзкие звери — причина, по которой я изначально прокомментировал.
Ответ №2:
Вся цель шаблона удаления — поддерживать уникальный using (temporaryObject)
шаблон C #. У Java не было ничего подобного этому шаблону до 7.
Все объекты Java, у которых были ресурсы, поддерживали шаблон удаления путем ручного закрытия объекта, содержащего ресурсы.
Комментарии:
1. Я знаю, что это старый пост, но для полноты картины справедливо сказать, что все наоборот. Вся цель
using
состоит в том, чтобы гарантировать, что одноразовые объекты в локальном контексте действительно удаляются, не требуя вложения try / finally. Сам одноразовый шаблон часто используется вне локального контекста и, следовательно, безusing
него, особенно если удаляемый объект содержит ссылки на другие одноразовые объекты.
Ответ №3:
То, что вы ищете, — это попробовать с ресурсами.
try ( FileInputStream input = new FileInputStream(...);
BufferedReader br = new BufferedReader(...) ) {
// Use input
}
Конечно, ресурс должен быть закрываемым (или автоматически закрываемым).
Комментарии:
1. Из вопроса OPs ясно, что он уже знает об этом и что он спрашивает, как это можно было сделать до Java 7…