source

Jackson의 ObjectMapper를 정적 필드로 선언해야 합니까?

factcode 2022. 8. 12. 23:15
반응형

Jackson의 ObjectMapper를 정적 필드로 선언해야 합니까?

잭슨 도서관ObjectMapper클래스는 안전한 것 같습니다.

이 말은 제가 제 개인 신분을ObjectMapper이와 같은 정적 장으로서

class Me {
    private static final ObjectMapper mapper = new ObjectMapper();
}

인스턴스 수준의 필드가 아니라요?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}

네, 그것은 안전하고 추천할 만한 것입니다.

참조한 페이지의 유일한 경고는 매퍼가 공유되면 설정을 변경할 수 없다는 것입니다.다만, 설정을 변경하지 않기 때문에 문제가 없습니다.설정을 변경할 필요가 있는 경우는, 스태틱블록부터 변경해도 괜찮습니다.

편집: (2013/10)

2.0 이상에서는 더 나은 방법이 있다는 점에 주목함으로써 위의 내용을 강화할 수 있습니다. 바로 사용법입니다.ObjectWriter그리고.ObjectReader오브젝트, 이 오브젝트는ObjectMapper완전히 불변하고 스레드 세이프합니다.즉, 이론적으로는 스레드 세이프티 문제를 일으킬 수 없습니다(이러한 문제는ObjectMapperinstance를 재구성하려고 할 경우).

Object Mapper는 스레드 안전하지만 특히 멀티스레드 어플리케이션에서는 이를 스태틱 변수로 선언하지 않습니다.나쁜 관행이기 때문이 아니라 교착 상태에 빠질 위험이 크기 때문입니다.나는 내 경험으로 그것을 말하고 있다.웹 서비스에서 JSON 데이터를 가져와 처리하는 4개의 동일한 스레드로 애플리케이션을 만들었습니다.스레드 덤프에 따르면 어플리케이션이 다음 명령어로 자주 정지하고 있었습니다.

Map aPage = mapper.readValue(reader, Map.class);

그 외에 퍼포먼스가 좋지 않았다.static 변수를 instance 기반 변수로 대체하면 지연이 사라지고 성능이 4배로 향상되었습니다.즉, 240만 건의 JSON 문서가 40분 만에 처리되었습니다.2.5시간 전에서 56초 전으로요

정적 최종 변수로 정의하지 않고 약간의 오버헤드를 줄이고 스레드의 안전성을 보장하고자 하는 경우 이 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();
}

저자의 공로를 인정

스레드 안전성 측면에서는 스태틱오브젝트매퍼를 선언하는 것이 안전하지만 Java에서 스태틱오브젝트 변수를 작성하는 것은 잘못된 관행으로 간주됩니다.자세한 내용은 정적 변수가 악으로 간주되는 이유를 참조하십시오.(원하신다면, 제 대답입니다)

즉, 는 간결한 유닛테스트를 기술하기 어렵기 때문에 스태틱스는 피해야 합니다.예를 들어 정적 최종 ObjectMapper를 사용하면 JSON 시리얼화를 더미 코드 또는 no-op으로 스왑할 수 없습니다.

또한 static final을 사용하면 실행 시 ObjectMapper를 재구성할 수 없습니다.지금은 그 이유를 상상하지 못할 수도 있지만, 정적인 최종 패턴에 자신을 잠그면 클래스 로더를 분해하는 것 외에는 클래스 로더를 재초기화할 수 없습니다.

Object Mapper의 경우 문제가 없지만 일반적으로는 잘못된 관행이며, 긴 수명을 가진 개체를 관리하기 위해 싱글톤 패턴이나 제어 반전 기능을 사용하는 것보다 더 좋은 점은 없습니다.

com.sysml.syslogind.type을 지정합니다.Type Factory 를 입력합니다._hash Map Super인터페이스 체인(계층형)

com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
  com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
     com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
        com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
           com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
              com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
                 com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
                    com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)

메서드 _hashMapSupercom.fasterxml.jackson.databind.type 클래스의 InterfaceChain.TypeFactory가 동기화되어 있습니다.높은 부하에서도 같은 경합이 발생하고 있습니다.

정적 Object Mapper를 피해야 하는 다른 이유일 수 있습니다.

이 질문은 오래된 것일 수도 있지만, 제가 하는 일은 이렇습니다.

★를 합니다.ObjectMapper'CHANGE: 'CHANGE: 'CHANGE: 'CHANGE: 'CHANGE:

public final class JacksonObjectMapperHolder {

  private static volatile JacksonObjectMapperHolder INSTANCE;

  private static final Object MUTEX = new Object();

  public static JacksonObjectMapperHolder getInstance() {
    JacksonObjectMapperHolder instance = INSTANCE;

    if(instance == null) {
      synchronized(MUTEX) {
        instance = INSTANCE;

        if(instance == null) {
          INSTANCE = instance = new JacksonObjectMapperHolder();
        }
      }
    }

    return instance;
  }

  private final ObjectMapper objectMapper = new ObjectMapper();

  private JacksonObjectMapperHolder() {
    super();
  }

  public final ObjectMapper getObjectMapper() {
    return objectMapper;
  }

}

언급URL : https://stackoverflow.com/questions/3907929/should-i-declare-jacksons-objectmapper-as-a-static-field

반응형