2012-03-01 14 views
8

Sto ricevendo la seguente violazione riportata da StrictMode in Android.StrictMode si lamenta che InputStream non viene chiuso

02-05 04: 07: 41,190: ERRORE/StrictMode (15093): Una risorsa è stata acquisita in allegato traccia dello stack, ma mai rilasciato. Vedi java.io.Closeable for informazioni su come evitare perdite di risorse. 02-05 Aprile: 07: 41,190: ERRORE/StrictMode (15093): java.lang.Throwable: terminazione esplicita metodo 'stretta' non chiama

Si cribbing di non chiudere i flussi in modo corretto. Tuttavia, non dovrebbe chiudere in chiudere i flussi sottostanti? Quale potrebbe essere la ragione per l'errore segnalato?

private ArrayList<Uri> loadPath() { 
     ArrayList<Uri> uris = new ArrayList<Uri>(); 
     if (mFile.exists()) { 
      ObjectInputStream in = null; 
      try { 
       in = new ObjectInputStream(new BufferedInputStream(
         new FileInputStream(mFile), STREAM_BUFFER_SIZE)); 
       ArrayList<String> strings = new ArrayList<String>(); 
       strings.addAll((ArrayList<String>) in.readObject()); 
       for (String string : strings) { 
        uris.add(Uri.parse(string)); 
       } 
      } catch (Exception e) { 
       mFile.delete(); 
      } finally { 
       IOUtils.closeQuietly(in); 
      } 
     } 
     return uris; 
    } 

    public static void closeQuietly(InputStream input) { 
     try { 
      if (input != null) { 
       input.close(); 
      } 
     } catch (IOException ioe) { 
      // ignore 
     } 
    } 
+0

Non sono sicuro di quanto sia intelligente il correttore StrictMode, ma sembra essere confuso dal *** *** rinviato ***, ovvero utilizzando un'utilità per chiudere il flusso per te. – Perception

+0

Nel mio caso ottengo questo errore anche quando 'close()' è in linea nella clausola 'finally'. –

risposta

0

Se si dà un'occhiata alla fonte ObjectOutpuStream, si vedrà che la sua stretta metodo chiude flusso sottostante. La modalità rigorosa di Android come molti altri strumenti di analisi del codice ha falsi positivi che puoi ignorare o riscrivere il tuo codice in modo che non si possa lamentare (metodo closeQuietly in linea).

+0

StrictMode di Android non è uno strumento di analisi del codice. È implementato in codice sorgente in 'FileInputStream' e' CloseGuard' in 'finalize()'. – pawelzieba

0

Il codice dovrebbe funzionare, a meno che non si utilizzi ProGuard che potrebbe rovinare un po 'con il bytecode.

FileInputStream ha ganci su CloseGuard che viene controllato in finalize() se l'istanza è stata chiusa. Questo è il motivo per cui penso che dovrebbe funzionare. La domanda è tempo close() è stato invocato o no?

Penso che sia stato creato FileInputStream (perché eccezione StrictMode ha generato) ma poi è stata lanciata un'eccezione infine e ignorata da qualche parte.

try { 
     if (input != null) { 
      input.close(); 
     } 
    } catch (Exception ioe) { 
     // check exception here 
    } 
9

Guardando il codice sorgente, i costruttori sia ObjectInputStream e BufferedInputStream può lanciare eccezioni che possano causare un oggetto FileInputStream da assegnare nella seguente riga, ma la variabile in sarà ancora nullo:

  in = new ObjectInputStream(
        new BufferedInputStream(
          new FileInputStream(mFile), 
        STREAM_BUFFER_SIZE) 
      ); 

da in è nullo quando otteniamo al blocco finally, che FileInputStream oggetto aperta non venga chiusa dal metodo closeQuietly(), causando StrictMode lamentare casualmente :)

La correzione più semplice vorrei suggerire è quella di dividere che l'assegnazione in 3 variabili e chiamare closeQuietly() su ciascuno, forse qualcosa di simile:

private ArrayList<Uri> loadPath() { 
    final ArrayList<Uri> uris = new ArrayList<Uri>(); 
    if (mFile.exists()) { 
     ObjectInputStream ois = null; 
     FileInputStream fis = null; 
     BufferedInputStream bis = null; 
     try { 
      fis = new FileInputStream(mFile); 
      bis = new BufferedInputStream(fis, STREAM_BUFFER_SIZE); 
      ois = new ObjectInputStream(bis); 
      final ArrayList<String> strings = new ArrayList<String>(); 
      strings.addAll((ArrayList<String>) ois.readObject()); 
      for (final String string : strings) { 
       uris.add(Uri.parse(string)); 
      } 
     } catch (final Exception e) { 
      mFile.delete(); 
     } finally { 
      closeQuietly(fis); 
      closeQuietly(bis); 
      closeQuietly(ois); 
     } 
    } 
    return uris; 
} 
+0

Ben individuato, ma nel mio caso non si verificano eccezioni.(Torno indietro e ricontrollato per essere assolutamente sicuro.) –

+0

Forse ho sbagliato qui, ma non StrictMode si lamenta anche di "possibili scenari"? Ad esempio, si lamenta dell'accesso IO dal thread principale, anche se in realtà nessun ANR è effettivamente causato. – dbm

+2

Si suppone che si lamenti di cose che effettivamente accadono. Nel caso di accesso IO sul thread principale, l'accesso all'IO avviene effettivamente sul thread principale. (Non è solo teorico.) Quindi, dovrebbe solo lamentarsi della perdita di InputStream se è realmente trapelata. –

0
in = new ObjectInputStream(new BufferedInputStream(
         new FileInputStream(mFile), STREAM_BUFFER_SIZE)); 

In questo esempio di codice si chiude solo il ObjectInputStream ma non BufferedInputStream o FileInputStream, è necessario chiuderli tutti.

+0

Sei tu? Questo contraddice la risposta di Konstantin Solomatov. –

+0

@GrahamBorland Basta fare un test e vedrai. –