Статьи

GC с автоматическим управлением ресурсами в Java 7

Этот пост содержит краткий обзор новой функции, представленной в Java 7, под названием «Автоматическое управление ресурсами» или «ARM». В статье рассказывается, как ARM пытается сократить код, который должен написать разработчик, чтобы эффективно освободить кучу выделенных ресурсов JVM.
Одним из самых приятных мест программирования на языке программирования Java является автоматическая обработка перераспределения объектов. В мире Java это более широко известно как сборка мусора; это в основном означает, что разработчикам не нужно беспокоиться об отмене выделения объекта, выделенного их кодом. Как только разработчик заканчивает использовать объект, он может аннулировать все ссылки на объект, и тогда объект становится пригодным для сборки мусора.
Однако сборка мусора имеет обратную сторону. В отличие от C / C ++, где кодер полностью контролирует выделение и перераспределение памяти (malloc, free, new, delete и т. Д.), В Java разработчик не имеет значительного контроля над процессом перераспределения объектов. JVM управляет процессом сбора мусора неиспользуемых объектов, и это действительно зависит от прихоти JVM, когда запускать цикл сбора мусора. Правда, есть вызовы методов, такие как System.gc () или Runtime.getRuntime (). Gc (), которые указывают, что сборка мусора будет запущена, но эти методы просто служат для напоминания JVM, что — «возможно, вам нужно запустить мусор» Сбор сейчас, просто предложение, никакого давления! ». JVM полностью авторизована, чтобы игнорировать такие запросы, и кодируется для запуска сборки мусора только тогда, когда это действительно целесообразно. Следовательно, на практике разработчикам всегда рекомендуется не создавать логику своей программы, полагая, что System.gc () или Runtime.getRuntime (). Gc () будут запускать полную сборку мусора.
Нельзя отрицать, насколько хорош автоматический сбор мусора для повышения производительности разработчиков. Однако есть некоторые случаи, когда сборка мусора недостаточна для поддержания «чистой» кучи, свободной от неиспользуемых объектов. Особенно, если объекты имеют дело с некоторой формой собственных ресурсов, обслуживаемых базовой операционной системой. Эти объекты включают, но не ограничиваются ими, потоки ввода-вывода, соединения с базой данных и т. Д. Для объектов такого типа разработчики должны явно освобождать ресурсы. Обычно это делается с помощью блоков try-catch.
Давайте посмотрим на небольшой пример, который закрывает InputStream после завершения обработки потока:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
InputStream in = null;
 
try
{
    in = new FileInputStream(new File("test.txt");
    //do stuff with in
}
catch(IOException ie)
{
    //SOPs
}
finally
{
    //do cleanup
}
Выше выглядит хорошо и чисто; однако, как только мы пытаемся закрыть входной поток с помощью in.close () в блоке finally, нам нужно окружить его блоком try-catch, который перехватывает проверенное исключение IOException. Таким образом, пример кода преобразуется в:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
InputStream in = null;
 
try
{
    in = new FileInputStream(new File("test.txt"));
    //do stuff with in
}
catch(IOException ie)
{
    //SOPs
}
finally
{
    try
    {
        in.close();
    }
    catch(IOException ioe)
    {
        //can't do anything about it
    }
}
Теперь приведенный выше код выглядит раздутым, и с несколькими видами проверяемых исключений в разных иерархиях нам нужно больше предложений catch. Очень скоро код становится длинным и сложным в обслуживании, не говоря уже о том, что код теряет свой первоначальный чистый и безошибочный вид, который даже привлекает внимание.
Но есть и хорошие новости.
Java 7 делает это проще с новым блоком try-catch. С помощью этой функции мы можем избежать самого блока finally. Вот как мы это делаем:
1
2
3
4
5
6
7
8
try(InputStream in = new FileInputStream(new File("test.txt"))
{
    //do stuff with in
}
catch(IOException ie)
{
    //SOPs
}
Приведенный выше блок кода выполняет саму часть очистки. Это стало возможным благодаря введению нового интерфейса, java.lang.AutoCloseable, который определяет один метод, void close () генерирует Exception . Объекты, которые являются подтипами этого интерфейса, могут автоматически закрываться () d с использованием приведенного выше синтаксиса. Вышеуказанная функция применима к объектам любого класса, которые реализуют интерфейс AutoCloseable.
Самое приятное то, что даже если мы инициализируем несколько экземпляров AutoCloseable в блоке try (), он вызовет метод close () для всех объектов, даже если какой-либо метод close () какого-либо объекта вызовет какое-либо исключение.
Что касается обработки исключений, если были какие-либо исключения IOException в нашем блоке try, а также в неявном блоке finally (где AutoCloseable фактически закрываются), будет выброшено исключение, которое было сгенерировано в блоке try. а не в неявном блоке finally.
Однако у нас все еще могут быть детали неявного исключения блока finally из метода Throwable.getSuppressed (), который добавлен как новый метод в Java 7.
Я думаю, что функция автоматического управления ресурсами, или ARM, является отличным дополнением к Java 7.