2015-01-17 2 views
2

바람둥이 연결 풀링을 사용하고 있습니다. 그래서 원인이 된 두 범인 방법을 발견 나는 예외 org.apache.tomcat.dbcp.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2015-01-17 22:12:18 by the following code was never closed: 다음 시작 그런 removeAbandoned="true" logAbandoned="true" removeAbandonedTimeout="3"Tomcat 연결 풀 : 연결을 해제하지 않는 몇 가지 방법

:하지만 예외 다음되었다 org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

은 그래서 누수를 찾을 수있는 context.xml에서 다음 줄에 넣어 이 누출. 두 가지 방법은 연결을 얻는 일반적인 방법, 즉 드라이버 특정 연결에 액세스하기 위해 unwrap을 호출합니다.

try (Connection conn = DataSourceConnectionPool.getConnection().unwrap(OracleConnection.class); 
     OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall(MIGRATE_ACCOUNT)) { 
     ... 
     .... 
) 

중요한 것은 내가 JDK7 즉 자동 리소스 관리에서 try 블록을 사용하고 있다는 것입니다. 따라서 finally 블록이 필요 없습니다. 접속 종료는 JDK에 의해 자동으로 처리됩니다. 하지만 왜이 포장되지 않은 연결이 닫히지 않습니다. 그리고 나는 다음을 수행하려고 할 때 :

try (Connection poolConn = DataSourceConnectionPool.getConnection(); 
    Connection conn = poolConn.unwrap(OracleConnection.class); 

을 나는 java.sql.SQLException: Already closed. 어떻게 가까운이 연결을 얻고있다. try 블록을 사용하지 않고 수동으로해야합니까? 이 핸들을 처리 할 수있는 블록 핸들을 사용하면 안됩니까?

+0

첫 번째 질문은 당신이 할 수 .unwrap() 코드는 어디에서 누수가 발생하는 것을 확인했다 어떻게? –

답변

8

이것은 연결 풀의 잘못된 사용법입니다. 포장되지 않은 연결에서 close()으로 절대로 전화해서는 안됩니다.

풀링 된 연결을 사용하는 정상적인 흐름이

  1. Connection 취득하고, 풀은 물리적 연결을 얻고
  2. 당신은 당신은 close()를 호출 Connection
  3. 사용은 자신의 래퍼에 싸여 반환 Connection. 실제로는 이 닫히지 않고이면 풀의 래퍼가 close() 호출을 가로 채고 단순히 (여전히 활성 상태 인) 연결을 풀에 반환합니다.

풀이 래퍼 클래스 (예 : PoolableConnection, implements Connection)를 가지고 있기 때문에 작동합니다. PoolableConnection은 실제 작업을 수행하기위한 기본 연결에 위임하지만 다른 경우에는 close()을 다르게 구현합니다. 이로 인해 현재 PoolableConnection 래퍼가 삭제되고 연결 하위에 Connection이 연결 풀로 반환됩니다. 예를 들어.

이 방법은 프로그램 로직은 그냥하고자했다, 풀링되지 않은 정상 Connection로하는 DataSource에서 연결을 얻을 Connection 다음 close()를 사용할 수 있습니다.

연결 풀을 매우 쉽게 사용할 수있게하는 것은 바로이 투명성입니다.

이제 unwrap으로 전화하면 PooledConnection은 내부의 실제 Connection 대리인에게 액세스 권한을 제공합니다.

무엇 당신이 할 통화 close() 대리인입니다!

이 두 가지 효과가 있습니다하여 Connection가 풀에 반환되지 않도록

  1. 는, PooledConnectionclose()를 호출하지 않습니다.
  2. 풀 아래에서 연결이 끊어졌습니다. 풀이 끊어진 연결 자체를 처리하기 때문에 이것은 문제가되지 않습니다.

매우 신중해야합니다. 항상 풀에서 가져온 Connectionclose()으로 전화하여 풀로 반환하십시오. 절대 기본 연결에서 close()으로 전화하십시오.

그래서 코드가 있어야한다 : 내가 가지고있는

try (final Connection poolConn = DataSourceConnectionPool.getConnection()) { 
    final Connection conn = poolConn.unwrap(OracleConnection.class); 
    //do stuff with conn 
    //do not close conn!! 
} 
//poolConn is returned to the pool 
+1

좋은 글을 작성하세요. +1 –

관련 문제