TcpServer.handleAccept() synchronizes on this to add/remove/replace connections. However, this is TcpServer$Acceptor, which is wrong: it should be TcpServer.
The effect is that active connections (BaseServer.getConnection() can be added to the conns hashmap while handleAccept() does the same; as the 2 methods synchronize on different locks!
Solution: synchronized(this) --> synchronized(TcpServer.this)