Утечка ресурсов: in никогда не закрывается

86

Почему Eclipse дает мне теплые слова «Утечка ресурсов: 'in' никогда не закрывается» в следующем коде?

public void readShapeData() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
user1686995
источник

Ответы:

71

Потому что вы не закрываете свой сканер

in.close();
ногард
источник
40
Это закроет Scannerи отключит предупреждение, но оно также закроется, System.inчто обычно нежелательно.
Стюарт Кук
@StuartCook +1. Что-то, за чем нужно следить.
informatik01
8
Почему нужно закрывать Сканер? Что подразумевается под «утечкой ресурсов»?
Эрран Морад
1
@nogard: это ваш ответ действительно полезен .. но когда я использую in.close (); .. снова он показывает, что не может быть разрешено .. у меня есть код без обработки исключений .. спасибо
шт.
3
@StuartCook, вы забыли упомянуть, почему закрытие System.inобычно нежелательно. Это потому, что вы больше не сможете читать его. I. e. получишь, java.util.NoSuchElementException: No line foundесли попробуешь позвонить (new Scanner(System.in)).nextLine()например.
Петр Боднар
55

Как говорили другие, вам нужно вызвать «закрыть» классы ввода-вывода. Я добавлю, что это отличное место для использования блока try - finally без каких-либо уловок, например:

public void readShapeData() throws IOException {
    Scanner in = new Scanner(System.in);
    try {
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
    } finally {
        in.close();
    }
}

Это гарантирует, что ваш сканер всегда закрыт, что гарантирует надлежащую очистку ресурсов.

Точно так же в Java 7 или выше вы можете использовать синтаксис «попробуйте с ресурсами»:

try (Scanner in = new Scanner(System.in)) {
    ... 
}
Эрик Линдауэр
источник
2
Что подразумевается под утечкой ресурсов и как это повлияет на меня?
Эрран Морад
7
@Borat - «утечка ресурсов» означает, что какой-то системный ресурс (обычно память) теряется или расходуется напрасно. Обычно это влияет на вас, когда вы начинаете получать ошибки OutOfMemoryErrors во время нормальной работы вашей программы.
Эрик Линдауэр
Спасибо, Эрик. Я знаю, что вы можете вызвать ошибку, добавив строку к самой себе в бесконечном цикле. Я не уверен, как сканер мог вызвать эту ошибку.
Эрран Морад,
4
А как насчет попытки с ресурсами?
Деннис Менг
Спасибо, Деннис, добавил.
Эрик Линдауэр,
12

Вам нужен звонок in.close()в finallyблоке, чтобы убедиться, что это произойдет.

Из документации Eclipse, вот почему он отмечает эту конкретную проблему ( выделено мной ):

Классы, реализующие интерфейс java.io.Closeable (начиная с JDK 1.5) и java.lang.AutoCloseable (начиная с JDK 1.7), считаются представляющими внешние ресурсы, которые должны быть закрыты с помощью метода close (), когда они больше не нужны.

Компилятор Eclipse Java может анализировать, соответствует ли код, использующий такие типы, этой политике.

...

Компилятор помечает [нарушения] как «Утечка ресурсов:« поток »никогда не закрывается».

Полное объяснение здесь .

Будет
источник
7

Это говорит вам , что вам нужно , чтобы закрыть сканер вы инстанцированный на System.inс Scanner.close(). Обычно каждый ридер должен быть закрыт.

Обратите внимание: если вы закроете System.in, вы больше не сможете читать его. Вы также можете взглянуть на Consoleкласс.

public void readShapeData() {
    Console console = System.console();
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
    ...
}
Alex
источник
3
Обратите внимание, что System.console()это недоступно при запуске приложения через Eclipse, что может вызвать проблемы во время разработки.
Стюарт Кук
6

Если вы используете JDK7 или 8, вы можете использовать try-catch с ресурсами. Это автоматически закроет сканер.

try ( Scanner scanner = new Scanner(System.in); )
  {
    System.out.println("Enter the width of the Rectangle: ");
    width = scanner.nextDouble();
    System.out.println("Enter the height of the Rectangle: ");
    height = scanner.nextDouble();
  }
catch(Exception ex)
{
    //exception handling...do something (e.g., print the error message)
    ex.printStackTrace();
}
Agyeya
источник
Обратите внимание, что предложение catch не является обязательным. Если вы просто хотите, чтобы ресурс был закрыт даже в случае возникновения исключения, но оставьте обработку исключений, как в исходном коде OP (а именно, не пойманы вообще), вы можете просто использовать, tryкак показано, и не использовать catchпредложение.
user118967
5
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

Вышеупомянутая строка вызовет конструктор класса Scanner с аргументом System.in и вернет ссылку на вновь созданный объект.

Он подключен к входному потоку, который подключен к клавиатуре, поэтому теперь во время выполнения вы можете использовать пользовательский ввод для выполнения необходимой операции.

//Write piece of code 

Чтобы убрать утечку памяти -

in.close();//write at end of code.
Ааши
источник
3

добавление на private static Scanner in;самом деле не решает проблему, оно только очищает предупреждение. Создание статического сканера означает, что он остается открытым навсегда (или до тех пор, пока класс не будет выгружен, что почти «навсегда»). Компилятор больше не выдаст вам предупреждений, поскольку вы сказали ему «держать его открытым навсегда». Но это не то, чего вы действительно хотели, поскольку вам следует закрыть ресурсы, как только они вам больше не понадобятся.

HTH, Манфред.

user2393042
источник
2

Как правило, экземпляры классов, которые имеют дело с вводом-выводом, должны быть закрыты после того, как вы закончите с ними. Итак, в конце вашего кода вы можете добавить in.close().

аршаджи
источник
2
private static Scanner in;

Я исправил это, объявив in как частную статическую переменную класса Scanner. Не знаю, почему это исправлено, но я рекомендовал сделать именно это.

zachdyer
источник
5
вы отключили предупреждение, но создали утечку ресурсов
zacheusz
1

Сканер должен быть закрыт. Рекомендуется закрывать Readers, Streams ... и подобные объекты, чтобы освободить ресурсы и избежать утечек памяти; и сделать это в блоке finally, чтобы убедиться, что они закрыты, даже если при обработке этих объектов возникает исключение.

Карлос Камбон
источник
Этот ответ на самом деле помогает ОП понять, почему он должен закрыть вещь. Конечно, он может прочитать документ и увидеть " scanner.close()", но этот ответ действительно помогает ему / ей понять, что происходит. +1
HyperNeutrino
1

Ладно, серьезно, по крайней мере, во многих случаях это на самом деле ошибка. Он также отображается в VS Code, и линтер замечает, что вы достигли конца охватывающей области, не закрывая объект сканера, но не осознавая, что закрытие всех открытых файловых дескрипторов является частью завершения процесса. Утечки ресурсов нет, потому что все ресурсы очищаются при завершении, и процесс завершается, не оставляя места для хранения ресурса.

Чарли Мартин
источник
0
Scanner sc = new Scanner(System.in);

//do stuff with sc

sc.close();//write at end of code.
теджас
источник
-1
in.close();
scannerObject.close(); 

Он закроет Scannerи закроет предупреждение.

HRUTU.Z
источник