【问题标题】:StackOverflowError Jackson with SpringStackOverflowError Jackson 与 Spring
【发布时间】:2018-11-29 19:40:24
【问题描述】:

我与 Jackson 有一个 Spring Boot 项目。

每当我启动它时,我都会收到此异常(仅限生产环境)。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/apps/upiswitchv2/lib/upiswitchv2.jar!/BOOT-INF/lib/log4j-slf4j-impl-2.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/apps/upiswitchv2/lib/upiswitchv2.jar!/BOOT-INF/lib/slf4j-nop-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/apps/upiswitchv2/lib/upiswitchv2.jar!/BOOT-INF/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
2018-06-20 19:53:06,102 Log4j2-TF-1-AsyncLogger[AsyncContext@773cbf4f]-1 ERROR com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.lang.reflect.Parameter["declaringExecutable"]->java.lang.reflect.Method["parameters"]->java.lang.reflect.Parameter["declaringExecutable"]->java.lang.reflect.Method["parameters"]->java.lang.reflect.Parameter["declaringExecutable"]-

java.lang.reflect.Method["parameters"]->java.lang.reflect.Parameter["declaringExecutable"]->java.lang.reflect.Method["parameters"]->java.lang.reflect.Parameter["declaringExecutable"]->java.lang.reflect.Method["parameters"]->java.lang.reflect.Parameter["declaringExecutable"]->java.lang.reflect.Method["parameters"])

at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:706)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:256)
at com.fa.....................

Caused by: java.lang.StackOverflowError
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:709)
    ... 1011 more

配置

    <spring.boot.version>1.5.7.RELEASE</spring.boot.version>
    <jackson.version>2.8.5</jackson.version>

我还提供了customMessageConverter

@Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter =
        new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setSerializationInclusion(Include.NON_NULL);
    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}

我还添加了 Log4J Disruptor Jar 并添加了属性:

System.setProperty("log4j2.contextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

另一个观察结果:每当我收到MethodArgumentNotValidException 时,StackOverflowErrors 就会增加

例如,如果我使用@Pattern 注解,如果验证失败,@RestControllerAdvice 会捕获MethodArgumentNotValidException,并在短时间内(100 毫秒)我在 SYSOUT 中得到一个StackOverflowError

【问题讨论】:

  • 请解释你的问题,因为上面的代码对我来说很好。
  • 代码对我来说也很好,在本地环境中。但是,我在生产中遇到了这个问题。我正在寻找调试此问题的提示。我会继续在这里发布我尝试过的任何内容。
  • 服务器上是否生成了检查日志?

标签: java spring spring-boot jackson stack-overflow


【解决方案1】:

看起来您正在序列化具有parametersdeclaringExecutable 属性的类。在这种情况下,parameters 包含对declaringExecutable 的引用,而declaringExecutable 又引用了对parameters 的引用。当类被序列化为 JSON 时,这会导致无限循环。

看看在一个地方或另一个地方删除引用。或者将链的一侧标记为@JsonIgnore

根据评论:

java.lang.reflect 仅用于尝试进行序列化的代码。如果您对declaringExecutableparameters 没有任何东西,那么您的某些代码肯定会尝试使用这些属性序列化库类。查看端点上的返回类型,看看您是否从具有该循环依赖关系的库中返回任何内容。

或者在问题中发布您的控制器类和任何其他序列化特定代码。

【讨论】:

  • 但那些是 java 类,不是我包的类
  • 答案中的更新注释
  • 您能否再解释一下:- 如何“查看您是否从具有该循环依赖关系的库中返回任何内容。”此外,加载类时服务器启动时出现异常,我如何缩小嫌疑人的范围。我可以打开一些日志来帮助我调试这个问题吗?
  • 可能很难用日志记录来解决,因为它发生在启动时,但我肯定会将日志调用添加到您期望最终结果为 JSON 的任何控制器方法。作为启动过程的一部分,还要检查您要序列化为 JSON 的任何内容。在此处发布您的 Controller 类以获取更多详细信息
  • 我有几件事要分享,验证后也会在问题中分享详细版本:1)代码中有一个自定义转换器,它消耗表单/url编码的请求并自动将它们转换为JSON。 2)只有1个Api消耗=“application/json”(其余都是消耗=“application/x-www-form-urlencoded”),它是验证失败时,有时我会看到一个stackOverflow错误3)第2点只是一个理论,可能是错误的,需要验证它,我很快就会这样做并在这里发布结果
猜你喜欢
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多