Closed wyhasany closed 3 years ago
It seems that's happened because I've shared Pool<Kryo>
between many instance of KryoRedisSerializer
as the pool was static.
Oh, it seems I've been mistaken. It's looks like that we can't use Pool
with threadSafe=true
and softReference=true
in multithread env. As under congestion the limit of the queue can be reached.
Then: freeObjects.offer(object) at at com.esotericsoftware.kryo.util.Pool.free(Pool.java:95)
calls SoftReferenceQueue.offer
which delegates call to queue delegate.add()
to this anonymously extended LinkedBlockingQueue
:
queue = new LinkedBlockingQueue<T>(maximumCapacity) {
@Override
public boolean add (T o) {
if (size() >= maximumCapacity) return false;
super.add(o);
return true;
}
};
there is size checking, however we don't have here any locking, so the size could be changed by the another thread. Then super.add(o)
can throw exception which is nowhere handled. To protect ISE Queue full you can just make following change:
- if (size() >= maximumCapacity) return false;
- super.add(o);
- return true;
+ return super.offer(o);
PR is merged and will be part of the next release. Thanks!
Until the release of Kryo 5.0.4 (probably). If you've found similar bug the basic workaround is switching off soft references:
//fails
Pool<Kryo> kryoPool = new Pool<Kryo>(true, true, 16);
//passes
Pool<Kryo> kryoPool = new Pool<Kryo>(true, false, 16)
Since the next release the first version would work smoothlessly in multi-threaded environment.
@theigl thanks for cooperation 👍
Using com.esotericsoftware.kryo.util.Pool with threadSafe = true and softReferences = false and a limit.
I'm running following code under JMH with 8 concurrent threads. Is that correct behavior?