FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.52k stars 1.38k forks source link

AnnotatedCreatorCollector._findPotentialFactories throws NullPointerException in Jackson 2.9.9.3 #2994

Closed aftool closed 3 years ago

aftool commented 3 years ago

Describe the bug Recently I upgrade jackson-databind in my application from version 2.8.7 to 2.9.9.3, it works for two weeks then we encounter NPE throwed from AnnotatedCreatorCollector._findPotentialFactories, and the issue is gone after I restart my server. Here is the full stack trace:

java.lang.NullPointerException
 at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector._findPotentialFactories(AnnotatedCreatorCollector.java:183)
 at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector.collect(AnnotatedCreatorCollector.java:57)
 at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector.collectCreators(AnnotatedCreatorCollector.java:47)
 at com.fasterxml.jackson.databind.introspect.AnnotatedClass._creators(AnnotatedClass.java:381)
 at com.fasterxml.jackson.databind.introspect.AnnotatedClass.getFactoryMethods(AnnotatedClass.java:293)
 at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.getFactoryMethods(BasicBeanDescription.java:534)
 at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerFactoryMethods(BasicDeserializerFactory.java:852)
 at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:349)
 at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:269)
 at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.createCollectionDeserializer(BasicDeserializerFactory.java:1222)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:399)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
 at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
 at com.fasterxml.jackson.databind.DeserializationContext.findNonContextualValueDeserializer(DeserializationContext.java:467)
 at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:473)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
 at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
 at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
 at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
 at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4191)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4010)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
 at com.pactera.powerweb.util.JsonUtil.strToObj(JsonUtil.java:68)
 at com.pactera.powerweb.base.BaseService.getSessionObject(BaseService.java:313)
 at com.pactera.pcm.keyInfoApp.service.PcmKeyInfoAppService.updateKeyInfoApp(PcmKeyInfoAppService.java:233)
 at com.pactera.pcm.keyInfoApp.service.PcmKeyInfoAppService$$FastClassBySpringCGLIB$$ce1f845d.invoke(<generated>)
 at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
 at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
 at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
 at com.pactera.pcm.keyInfoApp.service.PcmKeyInfoAppService$$EnhancerBySpringCGLIB$$901ee118.updateKeyInfoApp(<generated>)
 at com.alibaba.dubbo.common.bytecode.Wrapper190.invokeMethod(Wrapper190.java)
 at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
 at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
 at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
 at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:65)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:70)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
 at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
 at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:113)
 at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
 at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
 at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
 at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1157)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:627)
 at java.lang.Thread.run(Thread.java:809)

I look into the code that throws nullpointerexception

    private List<AnnotatedMethod> _findPotentialFactories(JavaType type, Class<?> primaryMixIn)
    {
        List<Method> candidates = null;

        // First find all potentially relevant static methods
        for (Method m : ClassUtil.getClassMethods(type.getRawClass())) {
            if (!Modifier.isStatic(m.getModifiers())) {
                continue;
            }
            // all factory methods are fine:
            //int argCount = m.getParameterTypes().length;
            if (candidates == null) {
                candidates = new ArrayList<>();
            }
            candidates.add(m);
        }

encountered nullpointerexception at

            if (!Modifier.isStatic(m.getModifiers())) {

my code is like:

public class JsonUtil
{
...
  public static <T> T strToObj(String str, Class<T> clazz)
  {
    try
    {
      ObjectMapper objectMapper = new ObjectMapper();

      return objectMapper.readValue(str, clazz);
    } catch (JsonParseException e) {
      e.printStackTrace();
    } catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
...
}

Version information version 2.9.9.3 (upgrade from 2.8.7 to 2.9.9.3)

To Reproduce Sorry I'm unnable to reproduce the issue, the issue has disappeared after I restart my server.

cowtowncoder commented 3 years ago

Hi there! I understand that it is not easy to reproduce this, but will tag this as "need-test-case" since without one it is not really possibly to verify the a fix works.

Since version 2.9 is will not be maintained after end of this month (there will be one more micro-patch, but just for known security issue(s)), I would recommend anyone who might see the issue to upgrade to a later minor version first: 2.10.5 would be the safest choice. If reproducible, still, this may be re-opened for investigation.

aftool commented 3 years ago

Hi, thanks for your response. I understand that reproduce will be important to identify the issue. actually my biggest problem is that I can't not reproduce this issue in test environment. Do you have any clue in what case will throw a NPE here, any clue will be useful for me.

Hi there! I understand that it is not easy to reproduce this, but will tag this as "need-test-case" since without one it is not really possibly to verify the a fix works.

Since version 2.9 is will not be maintained after end of this month (there will be one more micro-patch, but just for known security issue(s)), I would recommend anyone who might see the issue to upgrade to a later minor version first: 2.10.5 would be the safest choice. If reproducible, still, this may be re-opened for investigation.

cowtowncoder commented 3 years ago

@aftool I think that there were some rarely seen concurrency issues with some of class metadata introspection functionality in earlier Jackson 2.x version, in concurrent use cases. If so, you cannot reliably reproduce it. It would only happen rarely in certain sequence of usage. It is actually bit odd you would see it in 2.9 since I think most issues were with 2.8 and earlier.

If you can reproduce the issue with either 2.10.5 or 2.11.4, I will look at specific lines identified by stack traces and that could give some idea of what may be going on.

aftool commented 3 years ago

Yeah, this issue is really odd, cas it didn't happen for like two weeks, and after it occur then all the json transform failed with NPE. thanks for your advice, I will upgrade to version 2.10.5, to see if this issue happen again.

cowtowncoder commented 3 years ago

No reproduction for a newer version, closing. May be reopened with a reproduction (ideally unit test).