Какие последствия у незакрытия ресурсов (InputStream, Connection и т.д.) в Java?

«Какие последствия у незакрытия ресурсов (InputStream, Connection и т.д.) в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Незакрытие ресурсов приводит к утечкам ресурсов, которые могут вызвать серьезные проблемы в работе приложения.

Последствия:

  1. Утечка файловых дескрипторов – при достижении лимита ОС новые файлы/сокеты не смогут открываться.
  2. Исчерпание пула соединений БД – новые запросы будут блокироваться или падать с ошибками.
  3. Блокировка файлов – файлы остаются заблокированными для других процессов.
  4. Утечка памяти – ресурсы не освобождаются до сборки мусора.

Плохой пример:

public void readFile() {
    try {
        FileInputStream fis = new FileInputStream("data.txt");
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(fis)
        );
        // Чтение данных...
        // ЗАБЫЛИ закрыть reader и fis!
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Решение 1: try-with-resources (Java 7+) – рекомендуется:

public void readFile() {
    try (FileInputStream fis = new FileInputStream("data.txt");
         BufferedReader reader = new BufferedReader(
             new InputStreamReader(fis))) {
        // Автоматическое закрытие в обратном порядке
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Решение 2: Явное закрытие в finally:

public void readFile() {
    FileInputStream fis = null;
    BufferedReader reader = null;
    try {
        fis = new FileInputStream("data.txt");
        reader = new BufferedReader(new InputStreamReader(fis));
        // Чтение данных...
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (reader != null) reader.close();
            if (fis != null) fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Особые случаи:

  • AutoCloseable ресурсы – автоматически закрываются в try-with-resources
  • Соединения с БД – всегда возвращайте в пул через close()
  • Стримы Java 8+ – должны быть закрыты или использованы в try-with-resources

Best practice: Всегда используйте try-with-resources для любых ресурсов, реализующих AutoCloseable.