2013-04-12 2 views
26

나는 EntityUtils.consume(httpEntity);을 만났습니다. 그리고 나는 그것이 정말로 무엇을하는지 확신하지 못합니다. 예를 들어저자가 EntityUtils.consume (httpEntity);을 사용하는 이유는 무엇입니까?

다음 finally 블록이 연결을 종료하고 가비지 컬렉터가 httpEntity 처리됩니다 왜 저자가 EntityUtils.consume(httpEntity);에 넣어 않았다

try { 

    //... some code 

    HttpEntity httpEntity = httpResponse.getEntity(); 
    BufferedReader br = new BufferedReader(new InputStreamReader(http.Entity.getContent())); 
    String line; 
    while ((line = br.readLine())!= null) { 
     System.out.println(line); 
    } 
    EntityUtils.consume(httpEntity); 
} catch (Exception e) { 
    //code 
} finally { 
    httpClient.getConnectionManager().shutdown(); 
} 

?

답변

31

정말 "좋은 시민"(그리고 실제로는 HTTPClient 인터페이스의 계약을 알고 있음)로 귀결됩니다. EntityUtils.consume이 수행 할 작업은 httpEntity이 보유한 모든 리소스를 해제하는 것입니다. 이는 기본적으로 기본 스트림을 해제하고 연결 개체를 풀 (연결 관리자가 다중 스레드 된 스레드 인 경우)에 제공하거나 연결 관리자를 해제하여 다음 요청을 처리 할 수 ​​있습니다.

entity을 사용하지 않으면 실제로 "연결 관리자 종료 중"이 finally 절에 있음을 의미합니다. 수영장으로 보내지 않은 보류중인 스트림/연결을 닫을 수 있습니까? 나는 그것을 계약 적으로 할 것인지 확신하지 못한다. (비록 구현이 현명하다고 생각하지만). 그렇지 않으면 시스템 리소스 (소켓 등)가 누출 될 수 있습니다. 일어나는 일은 Entity 객체의 가능한 finalization 메소드에 달려있다. Entity 객체의 가능한 finalization 메소드는 리소스를 해제 할 수도있다.

잠시 동안 ConnectionManager이 실제로 종료 될 때 보류중인 모든 리소스를 정상적으로 닫는다고 가정 해 봅시다. 여전히 엔티티를 소비해야합니까? 나는 한 달 후에 누군가가 코드를 수정하고 동일한 try/finally 블록에서 두 번째 HTTP 호출을 할 것이기 때문에 네가 그렇다고 말하며, 리소스를 자유롭게하지 않아서 그렇게 할 수 없다 (예 : if 클라이언트가 단일 연결 풀에 있고 첫 번째 연결을 해제하지 않으면 두 번째 호출이 실패합니다.

요점은 다음과 같습니다. 엔티티는 리소스이며 필요하지 않을 때 리소스를 해제해야합니다. 다른 사람을 믿어 나중에 추방하면 나중에 당신을 해칠 수 있습니다. 원저자는 그 라인을 따라 생각했을 것입니다.

부수적으로, 작성한 구현은 실제로 독자 스트림을 끝까지 소비하므로 소비 호출은 실제로 아무 것도하지 않지만 실제로는 구현 세부 사항입니다 (내 머리 꼭대기에서 일단 응답 스트림이 완전히 읽혀지면 연결 개체는 자동으로 http 클라이언트의 풀로 보내지거나 다시 전송됩니다.) API가 제공하는 ResponseHandler 메카니즘을 사용하면이 소비 로직도 모두 사용자로부터 추상화됩니다. 마지막으로 API는 response.getEntity이 결코 null을 반환하지 않는다는 것을 보장하지 않으므로 NullPointerException을 피하도록 확인해야합니다.

관련 문제