2012-08-02 18 views
7

Eclipse (Juno) daje następujące ostrzeżenie:Dlaczego ten kod generuje ostrzeżenie o "potencjalnym wycieku zasobów"?

Potencjalny przeciek zasobu: 'os' nie mogą być zamknięte

w pierwszej linii ciała try w tym kodzie:

static void saveDetails(byte[] detailsData) { 
    OutputStream os = null; 
    try { 
     os = sContext.openFileOutput(DETAILS_FILE_NAME, Context.MODE_PRIVATE); 
     os.write(detailsData); 
    } catch (IOException e) { 
     Log.w(LOG_TAG, "Unable to save details", e); 
    } finally { 
     if (os != null) { 
      try { 
       os.close(); 
      } catch (IOException ignored) { 
      } 
     } 
    } 
} 

Metoda openFileOutput jest zadeklarowana jako rzut FileNotFoundException.

Czy to jest fałszywy alarm? Wydaje się, że jest to całkiem waniliowa analiza ścieżki wykonania.

+0

Byłoby łatwiej, gdybyś zaznaczył, które zaćmienie linii narzeka, ale zgaduję, że jest to związane z linią openFileOuput - Jak długo działa otwarty obiekt? Czy plik musi zostać zamknięty? – atk

+2

@atk - OP oznacza, że ​​ostrzeżenie znajduje się w pierwszym wierszu ciała próby. Więc 'os = sContext.OpenFileOutput ...'. –

+0

Jeśli 'sContext' ma wartość NULL, zostanie zgłoszony wyjątek NullPointerException, a na końcu nigdy nie zostanie uruchomiony, ponieważ nie jest złapanym wyjątkiem. W tym przypadku 'os' nie zostanie zamknięte (lub otwarte). –

Odpowiedz

11

Moim zdaniem jest to fałszywy alarm. Twój zasób jest zamknięty w "końcu" bloku, więc nie widzę, co może pójść nie tak.

Jako sidenote, jeśli korzystasz z Java 7, polecam użycie idiomu "try-with-resources".

static void saveDetails(byte[] detailsData) {  
    try (OutputStream os = sContext.openFileOutput(DETAILS_FILE_NAME, Context.MODE_PRIVATE);) { 
     os = sContext.openFileOutput(DETAILS_FILE_NAME, Context.MODE_PRIVATE); 
     os.write(detailsData); 
    } catch (IOException e) { 
     Log.w(LOG_TAG, "Unable to save details", e); 
    } 
} 
+0

Po prostu próbowałem, a IntelliJ nie uruchamia żadnego ostrzeżenia na twoim kodzie. To daje mi jeszcze więcej pewności co do tego, że jest on fałszywy w Eclipse. I tak, odważę się skomentować moją własną odpowiedź :) –

+0

Dzięki za test IntelliJ. Podoba mi się składnia Java 7, ale niestety jest to projekt Java 6.:( –

-2

Zgaduję, że to dlatego, że przed zamknięciem masz if (os != null). Ponieważ jest to warunkowe, możliwe jest, że OutputStream nie jest zamknięty.

Co się dzieje, jeśli spróbujesz:

static void saveDetails(byte[] detailsData) { 
    OutputStream os = null; 
    try { 
     os = sContext.openFileOutput(DETAILS_FILE_NAME, Context.MODE_PRIVATE); 
     os.write(detailsData); 
    } catch (IOException e) { 
     Log.w(LOG_TAG, "Unable to save details", e); 
    } finally { 
     try { 
      os.close(); 
     } catch (IOException ignored) { 
     } 
    } 
} 
+3

Następnie, jeśli 'os' * jest * null, rzucisz wyjątek NullPointerException w' końcu'. –

+0

Pytanie brzmi, czy 'sContext.openFileOutput' kiedykolwiek zwróci wartość null? –

+1

@SteveKuo Naprawdę pytanie brzmi, czy' openFileOutput "kiedykolwiek rzuca wyjątek w dowolnych okolicznościach." –

0

Co jeśli przenieść otwarte i blisko pierwszej klauzuli try? Rzucają ten sam wyjątek. I usuń jeśli os! = Null.

+1

To nie zadziała - blok 'try' może wyjść przedwcześnie z powodu wyjątku wygenerowanego przez' os.write', a następnie wywołanie 'os.close()' zostanie pominięte. –