带Spring的StackOverflowError杰克逊

Dip*_*rma 5 java stack-overflow spring jackson spring-boot

我和杰克逊有一个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
Run Code Online (Sandbox Code Playgroud)

组态

    <spring.boot.version>1.5.7.RELEASE</spring.boot.version>
    <jackson.version>2.8.5</jackson.version>
Run Code Online (Sandbox Code Playgroud)

我还提供了 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;
}
Run Code Online (Sandbox Code Playgroud)

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

System.setProperty("log4j2.contextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
Run Code Online (Sandbox Code Playgroud)

另一个观察结果:StackOverflowErrors每当我得到时增加MethodArgumentNotValidException

例如,如果我使用@Pattern批注,并且如果验证失败,@RestControllerAdvicecatchs MethodArgumentNotValidException,并且在短时间内(100毫秒),我StackOverflowError在SYSOUT中得到一个。

Joe*_*e W 8

像你看起来是序列化类的属性parametersdeclaringExecutable。在这种情况下parameters包含的参考declaringExecutable,进而declaringExecutable具有参考回parameters。当类被序列化为JSON时,这将导致无限循环。

看一下在一个位置或另一个位置移除参考。或将链条的一侧标记为@JsonIgnore

根据评论:

java.lang.reflect仅用于尝试进行序列化的代码。如果您没有任何东西,declaringExecutable并且parameters必须有一些代码正在尝试使用这些属性序列化库类。看一下端点上的返回类型,看看是否从具有该循环依赖关系的库中返回任何东西。

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