Класс 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создать ресурс, требующий очистки, и автоматически выполнять операции очистки, когда объект становится недостижимым:

Пример

import java.lang.ref.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, обеспечивающий эффективный и надёжный способ управления ресурсами.

Другие расширения