A thread-local for 
BufferPool.
 The BufferPoolThreadLocal is not assigned to a static field, but as a member field of the SerializationService-instance.
 is unlike the common use of a ThreadLocal where it assigned to a static field. The reason behind this is that the BufferPool
 instance belongs to a specific SerializationService instance (the buffer pool has buffers tied to a particular
 SerializationService instance). By creating a ThreadLocal per SerializationService-instance, we obtain 'BufferPool per thread
 per SerializationService-instance' semantics.
 
BufferPool is tied to SerializationService-instance
 The BufferPool contains e.g. 
BufferObjectDataOutput instances that have a reference to a specific
 SerializationService-instance. So as long as there is a strong reference to the BufferPool, there is a strong reference
 to the SerializationService-instance.
 
The problem with regular ThreadLocals
 In the Thread.threadLocal-map only the key (the ThreadLocal) is wrapped in a WeakReference. So when the ThreadLocal-instance
 dies, the WeakReference prevents a strong reference to the ThreadLocal and potentially at some point in the future, the map
 entry with the null valued WeakReference-key and the strong reference to the the value removed. The problem is we have
 no control when this happens and we could end up with a memory leak because there are strong references to e.g. the
 SerializationService.
 
BufferPoolThreadLocal wraps BufferPool also in WeakReference
 To prevent this memory leak, the value (the BufferPool) in the Thread.threadLocals-map is also wrapped in a WeakReference
 So if there is no strong reference to the BufferPool, the BufferPool is gc'ed. Even though there might by some empty key/value
 WeakReferences in the Thread.threadLocal-map.
 
Strong references to the BufferPools
 To prevent the BufferPool wrapped in a WeakReference to be gc'ed as soon as it is created, the BufferPool is also stored
 in the BufferPoolThreadLocal in a ConcurrentReferenceHashMap with a weak reference for the key (the thread) and a
 strong reference to the value (BufferPool):
 This gives us the following behavior:
 
 - 
 As soon as the Thread, having the ThreadLocal in its Thread.threadLocals-map, dies, the Entry with the Thread as key
 will be removed from the ConcurrentReferenceHashMap at some point.
 
- 
 As soon as the SerializationService is collected, the BufferPoolThreadLocal is collected. And because of this, there
 are no strong references to the BufferPool instances, and they get collected as well.
 
 So it can be that a Thread in its Thread.threadLocal-map will for some time have an empty weak-reference as key and value. But
 there won't be any references to the BufferPool/SerializationService.
 
Performance
 The Performance of using a ThreadLocal in combination with a WeakReference is almost the same as using a ThreadLocal without
 WeakReference. There is an extra pointer indirection and some additional pressure on the gc system since it needs to deal with
 the WeakReferences, but the number of threads is limited.