Java 我应该将 Jackson 的 ObjectMapper 声明为静态字段吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3907929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I declare Hymanson's ObjectMapper as a static field?
提问by Cheok Yan Cheng
The Hymanson library's ObjectMapper
class seems to be thread safe.
Hymanson 库的ObjectMapper
类似乎是线程安全的。
Does this mean that I should declare my ObjectMapper
as a static field like this
这是否意味着我应该将 my 声明ObjectMapper
为这样的静态字段
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
instead of as an instance-level field like this?
而不是像这样的实例级字段?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
采纳答案by StaxMan
Yes, that is safe and recommended.
是的,这是安全的,值得推荐。
The only caveat from the page you referred is that you can't be modifying configuration of the mapper once it is shared; but you are not changing configuration so that is fine. If you did need to change configuration, you would do that from the static block and it would be fine as well.
您引用的页面中唯一的警告是,一旦共享映射器,您就无法修改它的配置;但是您没有更改配置,所以很好。如果您确实需要更改配置,您可以从静态块中进行更改,也可以。
EDIT: (2013/10)
编辑:(2013/10)
With 2.0 and above, above can be augmented by noting that there is an even better way: use ObjectWriter
and ObjectReader
objects, which can be constructed by ObjectMapper
.
They are fully immutable, thread-safe, meaning that it is not even theoretically possible to cause thread-safety issues (which can occur with ObjectMapper
if code tries to re-configure instance).
对于 2.0 及更高版本,上面可以通过注意到有一种更好的方法来增强:使用ObjectWriter
和ObjectReader
对象,可以通过ObjectMapper
. 它们是完全不可变的、线程安全的,这意味着理论上甚至不可能导致线程安全问题(ObjectMapper
如果代码尝试重新配置实例,就会发生这种情况)。
回答by JBCP
Although it is safe to declare a static ObjectMapper in terms of thread safety, you should be aware that constructing static Object variables in Java is considered bad practice. For more details, see Why are static variables considered evil?(and if you'd like, my answer)
尽管在线程安全方面声明静态 ObjectMapper 是安全的,但您应该意识到在 Java 中构造静态 Object 变量被认为是不好的做法。有关更多详细信息,请参阅为什么静态变量被认为是邪恶的?(如果你愿意,我的回答)
In short, statics should be avoided because the make it difficult to write concise unit tests. For example, with a static final ObjectMapper, you can't swap out the JSON serialization for dummy code or a no-op.
简而言之,应该避免静态,因为这使得编写简洁的单元测试变得困难。例如,对于静态最终 ObjectMapper,您不能将 JSON 序列化替换为虚拟代码或无操作。
In addition, a static final prevents you from ever reconfiguring ObjectMapper at runtime. You might not envision a reason for that now, but if you lock yourself into a static final pattern, nothing short of tearing down the classloader will let you re-initialize it.
此外,静态 final 会阻止您在运行时重新配置 ObjectMapper。您现在可能没有想到这样做的原因,但是如果您将自己锁定在静态最终模式中,那么除了拆除类加载器外,您还可以重新初始化它。
In the case of ObjectMapper its fine, but in general it is bad practice and there is no advantage over using a singleton pattern or inversion-of-control to manage your long-lived objects.
在 ObjectMapper 的情况下它很好,但一般来说这是不好的做法,与使用单例模式或控制反转来管理长期存在的对象相比没有优势。
回答by Gary Greenberg
Although ObjectMapper is thread safe, I would strongly discourage from declaring it as a static variable, especially in multithreaded application. Not even because it is a bad practice, but because you are running a heavy risk of deadlocking. I am telling it from my own experience. I created an application with 4 identical threads that were getting and processing JSON data from web services. My application was frequently stalling on the following command, according to the thread dump:
尽管 ObjectMapper 是线程安全的,但我强烈建议不要将其声明为静态变量,尤其是在多线程应用程序中。甚至不是因为这是一种不好的做法,而是因为您面临着严重的死锁风险。我是根据我自己的经验告诉它的。我创建了一个具有 4 个相同线程的应用程序,这些线程从 Web 服务获取和处理 JSON 数据。根据线程转储,我的应用程序经常停止执行以下命令:
Map aPage = mapper.readValue(reader, Map.class);
Beside that, performance was not good. When I replaced static variable with the instance based variable, stalling disappeared and performance quadrupled. I.e. 2.4 millions JSON documents were processed in 40min.56sec., instead of 2.5 hours previously.
除此之外,表现并不好。当我用基于实例的变量替换静态变量时,停顿消失了,性能翻了两番。即在 40 分 56 秒内处理了 240 万个 JSON 文档,而不是之前的 2.5 小时。
回答by Harshit
com.fasterxml.Hymanson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)
com.fasterxml.Hymanson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)
com.fasterxml.Hymanson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
com.fasterxml.Hymanson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
com.fasterxml.Hymanson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
com.fasterxml.Hymanson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
com.fasterxml.Hymanson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
com.fasterxml.Hymanson.databind.type.TypeFactory._constructType(Type, TypeBindings)
com.fasterxml.Hymanson.databind.type.TypeFactory.constructType(TypeReference)
com.fasterxml.Hymanson.databind.ObjectMapper.convertValue(Object, TypeReference)
The method _hashMapSuperInterfaceChain in class com.fasterxml.Hymanson.databind.type.TypeFactoryis synchronized. Am seeing contention on the same at high loads.
com.fasterxml.Hymanson.databind.type.TypeFactory 类中的_hashMapSuperInterfaceChain方法是同步的。在高负载下看到相同的争用。
May be another reason to avoid a static ObjectMapper
可能是避免静态 ObjectMapper 的另一个原因
回答by Henry Lin
A trick I learned from this PRif you don't want to define it as a static final variable but want to save a bit of overhead and guarantee thread safe.
如果您不想将其定义为静态最终变量但想要节省一些开销并保证线程安全,我从这个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();
}
credit to the author.
归功于作者。