2013-02-27 21 views
5

Eclipse 4 đưa ra một cảnh báo mà nói stmt có thể có khả năng không được đóng cửa và gây ra rò rỉ tài nguyên:Trong trường hợp nào tài nguyên này sẽ bị rò rỉ?

class Test { 
    public void test() { 
     PreparedStatement stmt = null; 
     try { 
      stmt = HibernateSession.instance().connection().prepareStatement(""); 
     } catch (final SQLException e) { 
      e.printStackTrace(); 
     } finally { 
      if (stmt != null) 
       try { 
        stmt.close(); 
       } catch (final SQLException e) { 
        e.printStackTrace(); 
       } 
     } 
    } 
} 

Theo đó bối cảnh đó sẽ xảy ra?

+1

đó không phải là lỗi Eclipse tồi tệ nhất –

+1

@OlegMikheev đó không phải là lỗi, đó là một tính năng. Và tôi không có ý nói mỉa mai, nó thực sự là một tính năng hữu ích. – djechlin

+0

Tôi thích tính năng đó ... nó giúp tôi đôi khi, nhưng tôi không thể hiểu tại sao mã trên sẽ tạo ra cảnh báo quản lý tài nguyên - lỗi? –

Trả lời

2

Tôi đoán kết luận ở đây là: đây là lỗi của Eclipse?

+1

Trông giống như một lỗi Eclipse với tôi. Có lẽ Eclipse thấy rằng có một đường dẫn thông qua 'finally' (khi' stmt' là null) khiến 'stmt.close()' không được gọi. – Alex

-2

Bạn cần phải sử dụng thử Java 7 với tài nguyên hoặc thử-cuối cùng khối:

try(stmt = HibernateSession.instance().connection().prepareStatement("")) { 


} 

Cảnh báo này sẽ được tạo ra trên các loại mà kế thừa từ AutoCloseable mà không đảm bảo được đóng lại. (Hoặc có thể Closeable, tôi quên cái nào).

Bây giờ tôi thấy những gì bạn đang yêu cầu, chỉ cần viết mã ít phức tạp hơn.

Foo f = null; // don't do this, but it's what you're doing 
f = new Foo(); 

Là những gì bạn đang làm và bạn đã tìm thấy một trong nhiều tình huống mà bạn thực sự phải trả tiền phạt cho công việc không liên quan này.

Ngoài ra, try/finally của bạn phải sạch sẽ. .close() không thể ném, tại sao bạn lại bị bắt?

try { // don't do this 
    stmt.close(); 
} 
catch(SQLException exc) { 

} 

Nên tạo cảnh báo Eclipse cho bạn biết rằng bạn đang bắt thứ gì đó không bị ném. Đó thậm chí có thể là một lỗi biên dịch, không chắc chắn, nhưng có vẻ như bạn sẽ được hưởng lợi từ việc chơi với Eclipse> Preferences> Compiler và xem lại những cảnh báo nào là thông minh. Nếu bạn không hiểu cảnh báo, hãy google và xem nó có hữu ích cho bạn hay không, đừng bỏ qua nó. (giống như bạn đã làm với cái này).

+1

cảm ơn, điều đó sẽ làm cho mã rõ ràng hơn nhiều. Tôi muốn chủ nhân của tôi sẽ thích ứng với jdk 1.7. –

+1

[ý bạn là gì _.close() không thể ném_?] (Http://docs.oracle.com/javase/6/docs/api/java/sql/Statement.html#close%28%29) –

+1

@OlegMikheev xấu của tôi, tôi ngầm giả định rằng lớp AutoCloseable được thiết kế chính xác (tôi đã mắc lỗi này trong Java trước đây). – djechlin

-1

Có thể xảy ra rò rỉ nếu xảy ra trường hợp ngoại lệ khi bạn gọi stmt.close() trong khối finally.

+1

và cách xử lý rò rỉ như vậy? –

-1

Vấn đề là trong khối finally ngoại lệ của bạn có khả năng xảy ra, điều này có thể ngăn không cho stmt đóng.

Một workaround là bạn có thể thay thế tất cả mọi thứ trong khối finally với:

JDBCUtilities.close(stmt); 

Xem docs cho JDBCUtilities.close. Như bạn có thể thấy, không có ngoại lệ nào được ném bằng phương thức tiện ích này, do đó bạn không cần phải lo lắng về việc rò rỉ tài nguyên. Một lợi ích nữa là phương pháp tiện ích cũng xử lý trường hợp null cho số stmt cũng như vậy chúng tôi không cần tự viết mã.

Thực ra, nó là good practice để sử dụng JDBCUtilities.

+0

Nó sẽ gây nhầm lẫn cho Eclipse nhiều hơn, điều này không thể biết được những gì 'JDBCUtilities.close (stmt)' thực hiện. – irreputable

+0

@irreputable Làm cách nào? Eclipse chỉ kiểm tra lỗi cú pháp, ngoại lệ đã kiểm tra, v.v. Tôi không nghĩ rằng nó quan tâm hoặc hiểu logic kinh doanh. Trong khối 'finally', chúng ta muốn đóng' stmt' chính xác là những gì 'JDBCUtilities.close' thực hiện. –

+0

Eclipse không biết rằng 'JDBCUtilities.close (stmt)' gọi 'stmt.close()' – irreputable

Các vấn đề liên quan