首页 > 解决方案 > 不可能的 nullPointerException 关于 java 反射

问题描述

最近我从第三方 jar 中遇到了 NullPointerException 问题,在我深入研究代码后仍然无法弄清楚它是如何发生的。这是错误堆栈跟踪

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)

它说 npe 发生在 AnnotatedCreatorCollector 类的第 183 行,这是 AnnotatedCreatorCollector 的代码和行号

177    private List<AnnotatedMethod> _findPotentialFactories(JavaType type, Class<?> primaryMixIn)
178    {
179        List<Method> candidates = null;
180
181        // First find all potentially relevant static methods
182        for (Method m : ClassUtil.getClassMethods(type.getRawClass())) {
183            if (!Modifier.isStatic(m.getModifiers())) {
184                continue;
185            }
186            // all factory methods are fine:
187            //int argCount = m.getParameterTypes().length;
188            if (candidates == null) {
189                candidates = new ArrayList<>();
190            }
191            candidates.add(m);
192        }

我能想象这个 npe 会发生的唯一条件是局部变量“m”为空,然后我深入研究 ClassUtil 类,它就可以了

    public static Method[] getClassMethods(Class<?> cls)
    {
        try {
            return ClassUtil.getDeclaredMethods(cls);
        } catch (final NoClassDefFoundError ex) {
            // One of the methods had a class that was not found in the cls.getClassLoader.
            // Maybe the developer was nice and has a different class loader for this context.
            final ClassLoader loader = Thread.currentThread().getContextClassLoader();
            if (loader == null){
                // Nope... this is going to end poorly
                throw ex;
            }
            final Class<?> contextClass;
            try {
                contextClass = loader.loadClass(cls.getName());
            } catch (ClassNotFoundException e) {
                ex.addSuppressed(e);
                throw ex;
            }
            return contextClass.getDeclaredMethods(); // Cross fingers
        }
    }
    public static Method[] getDeclaredMethods(Class<?> cls) {
        return cls.getDeclaredMethods();
    }

我可以看到 ClassUtil 使用 java 反射返回一个方法数组,但我认为该数组不可能包含一个空对象,然后我就卡住了。

我的问题是:我们是否有可能通过java反射得到一个方法数组,并且该数组包含一个空对象?

这是我的代码

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;
  }
...
}

标签: javareflectionnullpointerexception

解决方案


推荐阅读