Витік ресурсу: "in" ніколи не закривається


84

Чому 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();

Відповіді:


69

Тому що ви не закриваєте свій сканер

in.close();

39
Це закриє Scannerі замовчить попередження, але також закриє, System.inщо зазвичай не бажано.
Стюарт Кук,

@StuartCook +1. Щось, за чим слідкувати.
informatik01

7
Чому нам потрібно закрити сканер? Що означає "витік ресурсів"?
Ерран Морад,

1
@nogard: ця ваша відповідь дійсно корисна .. але коли я використовую in.close (); .. знову це відображається, не може бути вирішено .. у мене є код без обробки винятків .. спасибі
шт

3
@StuartCook, ти забув згадати, чому закривати, System.inяк правило, не бажано. Це тому, що ви більше не зможете читати з нього. І. е. Ви отримаєте, java.util.NoSuchElementException: No line foundякщо спробуєте зателефонувати, (new Scanner(System.in)).nextLine()наприклад.
Петр Боднар,

55

Як казали інші, вам потрібно зателефонувати "закрити" на заняттях вводу-виводу. Додам, що це відмінне місце для використання спроби - нарешті, блокувати без улову, наприклад:

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-with-resources":

try (Scanner in = new Scanner(System.in)) {
    ... 
}

2
Що розуміється під витоком ресурсів і як це вплине на мене?
Ерран Морад,

7
@Borat - "витік ресурсу" означає, що деякий системний ресурс (зазвичай пам'ять) втрачається або марно витрачається. Зазвичай це вплине на вас, коли ви почнете отримувати OutOfMemoryErrors під час нормальної роботи вашої програми.
Ерік Ліндауер,

Дякую Еріку. Я знаю, що ви можете викликати помилку, додавши рядок до себе в нескінченному циклі. Я не впевнений, як сканер може спричинити цю помилку.
Ерран Морад

4
Як щодо спробувати ресурси?
Dennis Meng

Дякую Денніс, додав.
Ерік Ліндауер,

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: "));
    ...
}

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();
}

Зауважте, що застереження про лов не є обов’язковим. Якщо ви просто хочете переконатись, що ресурс закритий навіть у випадку винятку, але залишите обробку винятків, як у вихідному коді OP (а саме, не зафіксовано взагалі), ви можете просто використовувати, tryяк показано, і не використовувати catchпункт.
user118967

5
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

верхній рядок викличе конструктор класу сканера з аргументом System.in і поверне посилання на щойно побудований об'єкт.

Він підключений до вхідного потоку, який підключений до клавіатури, тому тепер під час виконання ви можете взяти введення користувача для виконання необхідних операцій.

//Write piece of code 

Щоб усунути витік пам'яті -

in.close();//write at end of code.


3

додавання private static Scanner in;насправді не вирішує проблему, воно лише очищає попередження. Якщо статичний сканер статичним, це означає, що він залишається відкритим назавжди (або до тих пір, поки клас не розвантажиться, що майже “назавжди”). Компілятор більше не попереджує вас, оскільки ви сказали йому "тримати його відкритим назавжди". Але це не те, що ви насправді хотіли, оскільки вам слід закрити ресурси, як тільки вони вам більше не знадобляться.

HTH, Манфред.


2

Як правило, екземпляри класів, що мають справу з введенням / виведенням, слід закривати після того, як ви закінчите з ними. Тож у кінці коду ви можете додати in.close().


2
private static Scanner in;

Я виправив це, оголосивши приватною змінною класу статичного сканера. Не впевнений, чому це виправлено, але саме це я рекомендував зробити затемнення.


5
ви приглушили попередження, але створили витік ресурсу
zacheusz

1

Сканер слід закрити. Це хороша практика - закривати Readers, Streams ... і подібні об’єкти, щоб звільнити ресурси та витік пам'яті; і робить це в блоці нарешті, щоб переконатися, що вони закриті, навіть якщо під час обробки цих об’єктів виникає виняток.


Ця відповідь насправді допомагає ОП зрозуміти, чому він повинен закрити річ. Звичайно, він може прочитати документ і побачити " scanner.close()", але ця відповідь дійсно допомагає йому / їй зрозуміти, що відбувається. + 1
HyperNeutrino

1

Добре, серйозно, принаймні у багатьох випадках це насправді помилка. Це також відображається у VS Code, і це лінтер, який зауважує, що ви досягли кінця охоплюючої області, не закриваючи об'єкт сканера, але не визнаючи, що закриття всіх дескрипторів відкритих файлів є частиною завершення процесу. Немає витоку ресурсів, оскільки всі ресурси очищаються при припиненні, і процес зникає, не залишаючи місця для зберігання ресурсу.



-1
in.close();
scannerObject.close(); 

Він закриє Scannerта закриє попередження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.