Objectmapper writeValueAsString 抛出 OOM 异常
Posted
技术标签:
【中文标题】Objectmapper writeValueAsString 抛出 OOM 异常【英文标题】:Objectmapper writeValueAsString throwing OOM Exception 【发布时间】:2020-04-24 15:43:33 【问题描述】:我反复使用 Jackson 的 writeValueAsString 方法将一个对象转换为一个字符串,就像重复了几千次一样。 JSON 的大小约为 1KB。但过了一会儿,我的程序退出并抛出 OOM 异常。以下是堆栈跟踪:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.lang.OutOfMemoryError: Java heap space
at com.fasterxml.jackson.core.util.TextBuffer.carr(TextBuffer.java:864)
at com.fasterxml.jackson.core.util.TextBuffer.expand(TextBuffer.java:825)
at com.fasterxml.jackson.core.util.TextBuffer.append(TextBuffer.java:590)
at com.fasterxml.jackson.core.io.SegmentedStringWriter.write(SegmentedStringWriter.java:58)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._writeString2(WriterBasedJsonGenerator.java:1013)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._writeString(WriterBasedJsonGenerator.java:982)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.writeString(WriterBasedJsonGenerator.java:377)
at com.fasterxml.jackson.databind.ser.std.StringSerializer.serialize(StringSerializer.java:41)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:718)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:639)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3893)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3207)
at com.ad2pro.neonmigration.neondatamigration.utils.NeonMetricsProducerUtil.produceImpressions(NeonMetricsProducerUtil.java:121)
at com.ad2pro.neonmigration.neondatamigration.scheduler.NeonScheduler.gerMetrics(NeonScheduler.java:100)
at com.ad2pro.neonmigration.neondatamigration.NeonDataMigrationApplication.main(NeonDataMigrationApplication.java:18)
... 8 more
java.lang.OutOfMemoryError: Java heap space
at javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:814)
at javax.crypto.CipherSpi.engineUpdate(CipherSpi.java:555)
at javax.crypto.Cipher.update(Cipher.java:2002)
at sun.security.ssl.CipherBox.decrypt(CipherBox.java:544)
at sun.security.ssl.EngineInputRecord.decrypt(EngineInputRecord.java:200)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:974)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at com.amazon.support.channels.TLSSocketChannel.read(Unknown Source)
at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)
~
在我的程序启动之前有 1GB 的可用内存。 objectmapper 是否持有大量内存,即使 1GB 也不足以将对象转换为字符串。任何帮助表示赞赏。
【问题讨论】:
要检查的一件事是对象是否具有导致无限循环的任何嵌套属性...这通常发生在编组具有双向关系的 JPA/Hibernate 实体时。 你需要展示你的代码,可能你有内存泄漏。 【参考方案1】:您可以尝试通过参数 -Xmx 和 -Xms 设置 JVM 堆。例如,告诉 Jvm 占用最大 512 mb 的堆 -Xms512m。
默认最大堆大小为 64 mb,这可能对您的程序来说还不够。
【讨论】:
【参考方案2】:这个问题有多个方面:
-
如上回答中所述,增加 JVM 堆占用 512 mb。
检查是否使用objectMapper对象转换为String
每次调用时创建。
writeAsString 不应导致无休止的字符串。
使用 visualVM 并检查导致堆增加的确切原因。
【讨论】:
以上是关于Objectmapper writeValueAsString 抛出 OOM 异常的主要内容,如果未能解决你的问题,请参考以下文章