Class StatementFinalizer
- All Implemented Interfaces:
InvocationHandler
Connection.close()
Useful for applications that don't close the associated statements after being done with a connection.
A statement is tracked with a strong reference until it is closed: an application that forgot about a statement is exactly the case the interceptor exists for, so finalisation must not depend on that statement still being reachable when the connection is returned. A statement closed through the handle this interceptor returns is forgotten at that moment, which keeps the tracked list bounded by the statements that are genuinely still open.
A close that reaches the statement by another route cannot be observed by that removal, so its entry is reclaimed at
the connection return: there the renewed close is a no-op on a statement the application had already closed, and the
close it still owed on one it had not. That assumes the swallowed close did not itself recycle the statement into a
cache: a recycling interceptor below this one would have parked it open, and the return-time close would then close
a statement a live cache entry still holds. StatementCache is the module's recycling interceptor and refuses
to park while it sits below this finalizer, so the ordering is safe for it; a third-party recycling interceptor is
not covered by that guarantee. A creation still in flight while the connection is returned is the one case that
return cannot reach - it registers after the return drained the list - and is closed where it arrives instead of
being tracked.
Tracked statements are normally handed to the application as proxies implementing the standard JDBC statement
interfaces, as is the statement facade the pool always installs in front of this interceptor and as are the proxies
of the other statement-wrapping interceptors; the driver's own statement class is then not reachable by casting. If
the tracking proxy cannot be created, the raw driver statement is returned instead and the statement stays tracked
until the connection is returned. The Wrapper methods are delegated to the driver, and
unwrap is the supported way to reach driver-specific statement methods. A statement the application
reaches that way is still tracked here and is closed, like any other tracked statement, when the connection is
returned - unless an interceptor listed after this one recycles the statement instead of closing it, as a statement
cache beneath this interceptor does.
Tracking covers the statements created through the pooled connection handle. A statement created on the driver's
own connection - the object Connection.unwrap(Connection.class) hands back - never reaches this
interceptor and is neither tracked nor closed when the connection is returned.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected classThin proxy around a tracked statement.protected classEntry that tracks a statement and its allocation stack. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected booleanWhether the connection return has already drainedstatements: set bycloseInvoked(), cleared byreset(ConnectionPool, PooledConnection)at the start of the next borrow.protected final List<StatementFinalizer.StatementEntry> Statements created on the associated connection that have not been closed yet.protected final ObjectMonitor guardingstatementsandreturnDrained.Fields inherited from class AbstractCreateStatementInterceptor
CREATE_STATEMENT, CREATE_STATEMENT_IDX, EXECUTE, EXECUTE_BATCH, EXECUTE_LARGE_BATCH, EXECUTE_LARGE_UPDATE, EXECUTE_QUERY, EXECUTE_TYPES, EXECUTE_UPDATE, GET_GENERATED_KEYS, GET_RESULTSET, GET_STATEMENT, PREPARE_CALL, PREPARE_CALL_IDX, PREPARE_STATEMENT, PREPARE_STATEMENT_IDX, RESULTSET_IDX, STATEMENT_TYPE_COUNT, STATEMENT_TYPESFields inherited from class JdbcInterceptor
ABORT_VAL, CLOSE_VAL, EQUALS_VAL, GETCONNECTION_VAL, HASHCODE_VAL, ISCLOSED_VAL, ISVALID_VAL, ISWRAPPERFOR_VAL, properties, TOSTRING_VAL, UNWRAP_VAL -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidMethod invoked when the operationConnection.close()is invoked.createStatement(Object proxy, Method method, Object[] args, Object statement, long time) This method will be invoked after a successful statement creation.voidreset(ConnectionPool parent, PooledConnection con) no-op for this interceptor. no state is stored.voidsetProperties(Map<String, PoolProperties.InterceptorProperty> properties) Called during the creation of an interceptor, once per instance: once for each instance created to build a pooled connection's interceptor chain, and once on the throwaway instance of each configured class that receivesJdbcInterceptor.poolStarted(ConnectionPool)at pool start andJdbcInterceptor.poolClosed(ConnectionPool)at pool close.Methods inherited from class AbstractCreateStatementInterceptor
elapsedMillis, getConstructor, invoke, isExecute, isStatement, processMethods inherited from class JdbcInterceptor
compare, compare, disconnected, getNext, getProperties, isUseEquals, poolClosed, poolStarted, setNext, setUseEquals, unregisterMBean
-
Field Details
-
statements
Statements created on the associated connection that have not been closed yet. Every access must be guarded bystatementsLock. -
statementsLock
Monitor guardingstatementsandreturnDrained. The pool's cleaner thread may clear the list (throughreset(ConnectionPool, PooledConnection)) while a borrower is still creating or closing statements on an abandoned connection, so subclasses that access either must hold this lock as well. -
returnDrained
protected boolean returnDrainedWhether the connection return has already drainedstatements: set bycloseInvoked(), cleared byreset(ConnectionPool, PooledConnection)at the start of the next borrow. Every access is guarded bystatementsLock.The driver's create has finished before this interceptor can register the statement, so a creation is not serialized against the connection return. One that lands after the return drained the list cannot be reclaimed by that return, and carrying it into the next borrow's books would only close it out from under the application still holding it;
createStatement(Object, Method, Object[], Object, long)closes it where it arrives instead.
-
-
Constructor Details
-
StatementFinalizer
public StatementFinalizer()Default constructor.
-
-
Method Details
-
createStatement
public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) Description copied from class:AbstractCreateStatementInterceptorThis method will be invoked after a successful statement creation. This method can choose to return a wrapper around the statement or return the statement itself. If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces.Statement,PreparedStatementorCallableStatementAn implementation must not make the statement reachable from any other code before it returns, because if this method throws then the statement is closed on a best-effort basis by the interceptor base class before the throwable is propagated to the application.
- Specified by:
createStatementin classAbstractCreateStatementInterceptor- Parameters:
proxy- the actual proxy objectmethod- the method that was called. It will be one of the methods defined inAbstractCreateStatementInterceptor.STATEMENT_TYPESargs- the arguments to the methodstatement- the statement that the underlying connection createdtime- elapsed time in milliseconds, measured with the monotonic clock- Returns:
- a
Statementobject
-
closeInvoked
public void closeInvoked()Description copied from class:AbstractCreateStatementInterceptorMethod invoked when the operationConnection.close()is invoked. It runs before the close is passed down the chain, so that a hook can still reach the connection while it is alive - statements must be closed before the session is handed to the next borrower. Implementation of this method should be thought through with care, as no actions should trigger an exception. An interceptor that nevertheless throws is isolated: the exception is logged and ignored, the remaining interceptors in the chain still receive the close, and the connection is returned to the pool as it would have been. The fatal virtual machine errors the pool never swallows are the exception: those propagate.- Specified by:
closeInvokedin classAbstractCreateStatementInterceptor
-
setProperties
Description copied from class:JdbcInterceptorCalled during the creation of an interceptor, once per instance: once for each instance created to build a pooled connection's interceptor chain, and once on the throwaway instance of each configured class that receivesJdbcInterceptor.poolStarted(ConnectionPool)at pool start andJdbcInterceptor.poolClosed(ConnectionPool)at pool close. The pool passes the live map of the interceptor definition, shared across all these instances, so it must be treated as read-only (seeJdbcInterceptor.getProperties()). Override this method to perform type casts between string values and object properties.- Overrides:
setPropertiesin classJdbcInterceptor- Parameters:
properties- The properties
-
reset
Description copied from class:AbstractCreateStatementInterceptorno-op for this interceptor. no state is stored.- Overrides:
resetin classAbstractCreateStatementInterceptor- Parameters:
parent- - the connection pool owning the connectioncon- - the pooled connection
-