I think here's a race condition with ObjectPool and RequestHandlerThread processing, since what can happen is that object pool called (CALL) and request handler thread (RH) can interleave like this:
# RH (in RequestHandler.run): this.objectPool.releaseRequestHandler(this)
# RH (in ObjectPool.releaseRequestHandler): this.unusedRequestHandlerThreads.add(rh)
# CALL (in ObjectPool.handleRequest): take RH from unusedRequestHandlerThreads
# CALL (in ObjectPool.handleRequest): rh.commenceRequestHandling(socket, listener);
# CALL (in RequestHandler.commenceRequestHandling): this.notifyAll()
# RH (in ObjectPool.run): this.wait()
Since notify is lost (no waiters), this.wait() in the last step will hang forever. This will leak a file descriptor since the socket given to be processed is never reclaimed, and threads are effectively lost as Winstone will then create more RequestHandlers.