2012-03-01 18 views
8

Tôi nhận được vi phạm sau đây được báo cáo bởi StrictMode trong Android.StrictMode phàn nàn về InputStream không bị đóng

02-05 04: 07: 41.190: ERROR/StrictMode (15093): Tài nguyên đã được mua tại dấu vết ngăn xếp được đính kèm nhưng không bao giờ được giải phóng. Xem java.io.Closeable để biết thông tin tránh rò rỉ tài nguyên. 02-ngày 05 tháng 4: 07: 41,190: LỖI/StrictMode (15.093): java.lang.Throwable: chấm dứt Explicit phương pháp 'gần' không được gọi

Nó được cribbing về việc không đóng cửa suối đúng cách. Tuy nhiên, không nên đóng in đóng các luồng cơ bản? Điều gì có thể là lý do cho lỗi được gắn cờ?

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

Không chắc chắn trình kiểm tra StrictMode thông minh như thế nào, nhưng có vẻ như nó bị nhầm lẫn bởi *** đóng *** bị trễ, tức là sử dụng tiện ích để đóng luồng cho bạn. – Perception

+0

Trong trường hợp của tôi, tôi nhận được lỗi này ngay cả khi 'close()' nằm trong mệnh đề 'finally'. –

Trả lời

0

Nếu bạn nhìn vào nguồn ObjectOutpuStream, bạn sẽ thấy phương pháp đóng của nó đóng luồng cơ bản. Chế độ nghiêm ngặt của Android giống như nhiều công cụ phân tích mã khác có sai tích cực mà bạn có thể bỏ qua hoặc viết lại mã của bạn để nó không phàn nàn (phương thức closeQuietly nội tuyến).

+0

StrictMode của Android không phải là công cụ phân tích mã. Nó được thực hiện trong mã nguồn xem xét 'FileInputStream' và' CloseGuard' trong 'finalize()'. – pawelzieba

0

Mã nên hoạt động, trừ khi bạn đang sử dụng ProGuard có thể gây rối một chút với bytecode.

FileInputStream có móc để CloseGuard được chọn để hoàn thành() nếu phiên bản đã được đóng. Đó là lý do tại sao tôi nghĩ rằng nó sẽ làm việc. Câu hỏi là thời tiết close() được gọi hay không?

Tôi nghĩ rằng FileInputStream đã được tạo (vì StrictMode ném ngoại lệ) nhưng sau đó ngoại lệ được ném vào cuối cùng và bỏ qua ở đâu đó.

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

Nhìn vào mã nguồn, các nhà thầu cho cả ObjectInputStreamBufferedInputStream có thể ném ngoại lệ đó sẽ gây ra một đối tượng FileInputStream được phân bổ vào các dòng sau, nhưng biến in vẫn sẽ được null:

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

in là không khi chúng tôi đến khối finally, mở đối tượng FileInputStream sẽ không bị đóng theo phương pháp closeQuietly() của bạn, gây ra StrictMode để khiếu nại cuối cùng :)

Việc sửa chữa đơn giản nhất tôi xin đề nghị là để chia phân bổ đó vào 3 biến và gọi closeQuietly() trên mỗi, có lẽ một cái gì đó như thế này:

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

Cũng phát hiện, nhưng trong trường hợp của tôi không có trường hợp ngoại lệ xảy ra.(Tôi sẽ quay lại và kiểm tra kỹ điều này để chắc chắn.) –

+0

Có lẽ tôi đã sai ở đây, nhưng StrictMode có phàn nàn về "các tình huống có thể xảy ra" không? Nó phàn nàn ví dụ về truy cập IO từ luồng chính, mặc dù không có ANR nào thực sự gây ra. – dbm

+2

Đó là nghĩa vụ phải phàn nàn về những thứ thực sự xảy ra. Trong trường hợp truy cập IO trên luồng chính, thực sự có truy cập IO xảy ra trên luồng chính. (Nó không chỉ là lý thuyết.) Vì vậy, nó chỉ nên phàn nàn về sự rò rỉ InputStream nếu nó thực sự đã bị rò rỉ. –

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

Trong mẫu mã này, bạn chỉ đóng ObjectInputStream nhưng không số BufferedInputStream hoặc FileInputStream, bạn cần phải đóng tất cả.

+0

Bạn có? Điều này mâu thuẫn với câu trả lời của Konstantin Solomatov. –

+0

@GrahamBorland Chỉ cần chạy thử nghiệm trên đó và bạn sẽ thấy. –