web-dev-qa-db-ja.com

StackOverflowError Jackson with Spring

私はジャクソンとのスプリングブートプロジェクトを持っています。

起動するたびに、この例外が発生します(実稼働環境のみ)。

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");

別の観察:StackOverflowErrorsを取得するたびに増加MethodArgumentNotValidException

たとえば、@Patternアノテーションを使用していて、検証が失敗した場合、@RestControllerAdviceMethodArgumentNotValidExceptionをキャッチし、短時間(100ミリ秒)にStackOverflowErrorを取得します。 SYSOUT。

5
Dipanshu Verma

parametersおよびdeclaringExecutableのプロパティを持つクラスをシリアル化しているようです。この場合、parametersにはdeclaringExecutableへの参照が含まれ、declaringExecutableにはparametersへの参照が含まれます。これにより、クラスがJSONにシリアル化されるときに無限ループが発生します。

いずれかの場所で参照を削除する方法を見てください。または、チェーンの片側を@JsonIgnoreとしてマークします

コメントに基づいて:

Java.lang.reflectは、シリアライゼーションを実行しようとしているコード専用です。 declaringExecutableparametersを使用して何もない場合は、これらのプロパティを使用してライブラリクラスをシリアル化しようとするコードが存在する必要があります。エンドポイントの戻り値の型を見て、循環依存関係を持つライブラリから何かを返しているかどうかを確認してください。

または、質問にコントローラークラスとその他のシリアル化固有のコードを投稿してください。

9
Joe W