Skip to content

Concurrency issue inside com.fasterxml.jackson.databind.util.LRUMap.get(Object) #503

@fjtc

Description

@fjtc

We just found an issue inside com.fasterxml.jackson.databind.util.LRUMap that result in a cache corruption when running on IBM J9 on high load.

The error manifests with the following stack (jackson-databind-2.4.1.1):

7799         at java.util.LinkedHashMap.get(LinkedHashMap.java:333)
7800         at com.fasterxml.jackson.databind.util.LRUMap.get(LRUMap.java:58)
7801         at com.fasterxml.jackson.databind.type.TypeFactory._fromClass(TypeFactory.java:707)
7802         at com.fasterxml.jackson.databind.type.TypeFactory._constructType(TypeFactory.java:387)
7803         at com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(TypeFactory.java:801)
7804         at com.fasterxml.jackson.databind.type.TypeFactory._constructType(TypeFactory.java:391)
7805         at com.fasterxml.jackson.databind.type.TypeBindings.resolveType(TypeBindings.java:102)
7806         at com.fasterxml.jackson.databind.introspect.Annotated.getType(Annotated.java:60)
7807         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._constructWriter(BeanSerializerFactory.java:703)
7808         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:559)
7809         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:344)
7810         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:263)
7811         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:222)
7812         at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:152)
7813         at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1077)
7814         at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1037)
7815         at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:445)
7816         at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:599)
7817         at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:92)
7818         at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2866)
7819         at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2289)

After analyzing the issue, we found out that the implementation of com.fasterxml.jackson.databind.util.LRUMap.get(Object) incorrectly assumes that the superclass implementation of this method is read-only. This is not true because the constructor of LRUMap sets the accessOrder to true, thus allowing get() to promote changes in the internal structure of the map in order to optimize the access (see http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html for further details).

Given that, the implementation of com.fasterxml.jackson.databind.util.LRUMap.get(Object) must be protect the call with a write lock instead of a read lock:

@Override
public V get(Object key) {
    _writeLock.lock();
    try {
        return super.get(key);
    } finally {
        _writeLock.unlock();
    }
}

It is also possible to solve this issue by changing the constructor parameter accessOrder to false instead and leave the current implementation of the get() as is. This however will disable the LRU behavior of this implementation.

I know that this change will result in performance issues due to the need of synchronization. I'll test the performance of other synchronization options as well in order to determine what is the best solution for this problem.

As far as I could see, this issue is closely related to the issue #435.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions