2013-04-10 3 views
0

Ниже приведен упрощенный пример, который будет вызывать вопрос системы Затмения Java предупреждение Potential resource leak: '<unassigned Closeable value>' may not be closed для выражения new BufferedWriter(...):Почему я получаю предупреждение о потенциальной утечке ресурсов с помощью объекта-обертки?

boolean useStdout = askUserWhetherToUseStdout(); 
    Writer writer = useStdout ? new OutputStreamWriter(System.out) : new BufferedWriter(new FileWriter(new File(askUserForFilename()))); 
    try 
    { 
     writer.write("Hello World!"); 
    } 
    finally 
    { 
     writer.close(); 
    } 

Является ли это ложноположительный? То, как я понял всю статью Писателя, заключается в том, что любой писатель закроет своих основных авторов. В моем случае writer будет инкапсулировать новый буферизованный писатель (который, в свою очередь, инкапсулирует файловый писатель), и поэтому закрытие writer не должно утечка каких-либо ресурсов, связанных с буферизованным писателем или, в свою очередь, его основных авторов?

Что мне здесь не хватает?

ответ

2

Edited ответ, основанный на обновленном вопрос:

Это фальшивое предупреждение - на основе использования трехкомпонентной оператора. Если правая сторона операции не срабатывает, то BufferedWriter не будет создан, и утечки ресурсов нет. Поэтому описание предупреждений на самом деле не является возможным. Однако, если вы хотите «обработать» его, просто переместите создание записи внутри блока try.

boolean useStdout = askUserWhetherToUseStdout(); 
Writer writer = null; 
try { 
    writer = useStdout ? new OutputStreamWriter(System.out) 
      : new BufferedWriter(new FileWriter(new File(
        askUserForFilename()))); 
    writer.write("Hello World!"); 
} finally { 
    if (writer != null) 
     writer.close(); 
} 
+0

Спасибо, но на самом деле я забыл добавить 'try' и' catch' в свой пример, так как они находятся в исходном коде. Предупреждение не имеет ничего общего с IOException. Я все равно получаю предупреждение, вы видите. – amn

+0

Если поток, в котором работает ваш код, был убит до выполнения блока finally, блок finally, возможно, никогда не будет выполнен, пока ваше приложение все еще продолжает работать. Dunno, если try-with-resource охватывает этот случай, но кажется вероятным. – Polygnome

+0

Это были важные детали. См. Обновленный ответ. – Perception

1

Если writer.write("Hello World!"); генерирует исключение, writer.close() никогда не вызывается.

Попробуйте обернуть его в блок try-catch (возможно, используя функцию автоматического закрытия, см. http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html).

+0

Спасибо, но на самом деле я забыл добавить 'try' и' catch' в свой пример, так как они находятся в исходном коде. Предупреждение не имеет ничего общего с IOException. По-прежнему я получаю предупреждение. – amn

1

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

boolean useStdout = askUserWhetherToUseStdout(); 
Writer writer = null; 
try { 
    writer = useStdout ? new OutputStreamWriter(System.out) 
      : new BufferedWriter(new FileWriter(new File(
        askUserForFilename()))); 
    writer.write("Hello World!"); 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    try { 
     if (writer != null) 
      writer.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Вы также можете использовать ресурсы try-with-resources, которые автоматически закрывают поток ресурсов после блока try.

boolean useStdout = askUserWhetherToUseStdout(); 
try (Writer writer = useStdout ? new OutputStreamWriter(System.out) 
     : new BufferedWriter(new FileWriter(new File(
       askUserForFilename())))) { 
    writer.write("Hello World!"); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
Смежные вопросы