Класс Cleaner в Java
java.lang.ref.Cleaner— это инструмент, появившийся в Java 9, предназначенный для управления очисткой объектов и обеспечивающий безопасный способ освобождения ресурсов во время сборки мусора. Он может заменитьfinalizeметод, который освобождает внешние ресурсы путём выполнения операций очистки, когда объект больше не используется, и являетсяfinalizeболее эффективным и надёжным.
1. CleanerРоль
CleanerПозволяет зарегистрировать действие очистки, которое будет автоматически выполнено, когда объект станет недостижимым (то есть когда вот-вот произойдёт сборка мусора). Типичные сценарии применения включают:
- Автоматически освобождать ресурсы памяти, не относящиеся к Java, такие как закрытие файлов, подключений к базе данных, сокетных соединений и т. д.
- Заменить
finalize, реализуйте автоматическое освобождение ресурсов, избегайте утечек ресурсов, вызванных забытым вызовомclose()метода.
2. CleanerБазовое использование
Ниже приведеноCleanerбазовое использование:
- Создайте
Cleanerпример:Cleaner.create()。 - Создайте объект, требующий очистки, и зарегистрируйте его вместе с действием очистки в
CleanerCleaner. Когда объект больше не имеет ссылок, действие очистки будет выполнено автоматически.
3. Пример использования
Следующий пример демонстрирует, как использоватьCleanerсоздать ресурс, требующий очистки, и автоматически выполнять операции очистки, когда объект становится недостижимым:
Пример
public class CleanerExample {
// Создать экземпляр Cleaner
private static final Cleaner cleaner = Cleaner.create();
// Определить ресурс, требующий очистки
static class Resource implements AutoCloseable {
// Задача очистки - используется для освобождения ресурсов
private final Cleaner.Cleanable cleanable;
Ресурс() {
// Зарегистрировать задачу очистки; выполнить действие очистки, когда экземпляр Resource станет недостижимым
this.cleanable = cleaner.register(this, new ResourceCleaner());
System.out.println("Ресурс инициализирован");
}
// Освободить ресурсы
private static class ResourceCleaner implements Runnable {
@Override
public void run() {
System.out.println("Очистка ресурса...");
}
}
@Override
public void close() {
// Активно освободить ресурсы и отменить задачу очистки, зарегистрированную в Cleaner
cleanable.clean();
System.out.println("Ресурс закрыт");
}
}
public static void main(String[] args) {
// Использовать ресурсы
try (Resource resource = new Resource()) {
System.out.println("Использование ресурса...");
} // Автоматически вызвать close() для ручной очистки ресурсов
// Если close() не вызван, GC выполнит задачу очистки
new Resource(); // Не вызывайте close(), дождитесь, пока GC инициирует очистку
System.gc(); // Подсказать GC запуститься (нет гарантии, что очистка выполнится немедленно)
}
}
4. Объяснение кода
- Экземпляр Cleaner::
Cleaner.create()создаётCleanerэкземпляр, используемый для регистрации ресурсов, нуждающихся в очистке. - Регистрация задачи очистки:В
Resourceклассе вызовитеcleaner.register(this, new ResourceCleaner())чтобы зарегистрировать текущий объект вCleanerCleaner, указав задачу очисткиResourceCleaner。 - Автоматическая очистка:Когда
Resourceэкземпляр не имеет других сильных ссылок и вот-вот будет собран сборщиком мусора,CleanerCleaner автоматически вызоветResourceCleaner.run()close(), выводя "Cleaning up resource...". - Ручная очистка:С помощью
close()активного вызова методаcleanable.clean(), немедленно очистите ресурсы и отменитеCleanerзадачу Cleaner.
5. Характеристики и преимущества Cleaner
- Эффективный:
CleanerУправляемый JVM, он избегаетfinalizeпроблем с низкой производительностью. - Избежание задержки finalize:
CleanerЗарегистрированные задачи могут быть выполнены сразу после того, как объект станет недостижимым, вместо ожидания отложенного вызова сборщиком мусора. - Управляемость:
CleanerПозволяет активно выполнятьclean()очистку ресурсов и автоматически отменяет задачу после очистки, избегая повторной очистки. - Безопасность памяти и ресурсов: снижает риск ручного управления ресурсами и обеспечивает корректное освобождение системных ресурсов.
6. Сценарии использования Cleaner
CleanerПодходит для управления ресурсами, требующими автоматического освобождения, особенно там, гдеtry-with-resourcesиспользование невозможно. Ниже приведены типичные сценарии применения:
- Нативные ресурсы: используются для управления ресурсами памяти вне кучи, например
DirectByteBuffer, JNI или другие локальные ресурсы. - Очистка кэша: когда объект собирается сборщиком мусора, автоматически очищаются связанные кэшированные данные.
- Неблокирующая очистка ресурсов: используется для задач неблокирующей очистки ресурсов, например для уведомления других сервисов о том, что объект был собран.
7. Примечания
- Использовать умеренно:
CleanerОн в основном используется для особых сценариев, таких как обеспечение отсутствия утечек не-Java-ресурсов. Для простого управления ресурсамиtry-with-resourcesлучше подходит. - Неконтролируемое время выполнения: Хотя
Cleanerего задача очистки болееfinalizeсвоевременна, но точное время выполнения задачи очистки всё ещё зависит от времени сборки мусора, что делает его непригодным для управления ресурсами с жёсткими требованиями к своевременности. - Будьте осторожны с ресурсоёмкими задачами очистки: Избегайте
Cleanerвыполнения в нём слишком сложных или длительных операций, чтобы не влиять на производительность сборки мусора.
В целом,java.lang.ref.Cleanerэто рекомендуемый инструмент очистки ресурсов в Java, обеспечивающий эффективный и надёжный способ управления ресурсами.