我应该将Jackson的ObjectMapper声明为静态字段吗?

时间:2010-10-11 16:08:13

标签: java json jackson

杰克逊图书馆ObjectMapperseems to be thread safe

这是否意味着我应该将ObjectMapper声明为像这样的静态字段

class Me {
    private static final ObjectMapper mapper = new ObjectMapper();
}

而不是像这样的实例级字段?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}

5 个答案:

答案 0 :(得分:458)

是的,这是安全的并且值得推荐。

您引用的页面中唯一的警告是,一旦共享,您就无法修改映射器的配置;但你没有改变配置,所以没关系。如果您确实需要更改配置,那么您可以从静态块执行此操作,它也可以。

编辑 :( 2013/10)

使用2.0及更高版本,可以通过注意更好的方法来增强上述内容:使用ObjectWriterObjectReader个对象,这些对象可以由ObjectMapper构建。 它们是完全不可变的,线程安全的,这意味着理论上甚至不可能导致线程安全问题(如果代码尝试重新配置实例,则可能会ObjectMapper发生)。

答案 1 :(得分:34)

虽然ObjectMapper是线程安全的,但我强烈建议不要将它声明为静态变量,尤其是在多线程应用程序中。 甚至不是因为这是一种不好的做法,而是因为你正面临着陷入僵局的沉重风险。我是根据自己的经验告诉你的。我创建了一个具有4个相同线程的应用程序,这些线程从Web服务获取和处理JSON数据。 根据线程转储,我的应用程序经常停在以下命令上:

Map aPage = mapper.readValue(reader, Map.class);

除此之外,表现并不好。 当我用基于实例的变量替换静态变量时,停顿消失了,性能翻了两番。即在40分57秒内处理了2.4百万个JSON文档,而不是之前的2.5小时。

答案 2 :(得分:2)

虽然在线程安全性方面声明静态ObjectMapper是安全的,但您应该知道在Java中构造静态Object变量被认为是不好的做法。有关详细信息,请参阅Why are static variables considered evil?(如果您愿意,请my answer

简而言之,应该避免静态,因为难以编写简洁的单元测试。例如,使用静态的最终ObjectMapper,您无法替换虚拟代码或无操作的JSON序列化。

此外,静态final会阻止您在运行时重新配置ObjectMapper。你现在可能没有想到这样的理由,但是如果你把自己锁定在一个静态的最终模式中,那么拆除类加载器就会让你重新初始化它。

在ObjectMapper的情况下它很好,但一般来说这是不好的做法,并且没有使用单例模式或控制反转来管理长期存在的对象的优势。

答案 3 :(得分:0)

如果您不想将其定义为静态最终变量,但又想节省一些开销并确保线程安全,则可以从PR中学到一个技巧。

private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
    @Override
    protected ObjectMapper initialValue() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }
};

public static ObjectMapper getObjectMapper() {
    return om.get();
}

致谢作者

答案 4 :(得分:-1)

com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)

com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
  com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
     com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
        com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
           com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
              com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
                 com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
                    com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)

com.fasterxml.jackson.databind.type.TypeFactory 中的方法_hashMapSuperInterfaceChain已同步。 我在高负荷时看到同样的争论。

可能是避免静态ObjectMapper的另一个原因

相关问题