Programing

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

lottogame 2020. 3. 5. 22:45
반응형

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


Jackson 라이브러리의 ObjectMapper클래스 는 스레드로부터 안전 합니다.

이것은 내가 ObjectMapper이것을 정적 필드로 선언해야한다는 것을 의미합니까?

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

이와 같은 인스턴스 레벨 필드 대신에?

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

예, 안전하고 권장됩니다.

언급 한 페이지에서 유일하게주의 할 점은 매퍼가 공유되면 매퍼의 구성을 수정할 수 없다는 것입니다. 그러나 구성을 변경하지 않으므로 괜찮습니다. 구성을 변경해야하는 경우 정적 블록에서 구성을 변경해도됩니다.

편집 : (2013/10)

사용 : 위 2.0으로, 위의 더 나은 방법이 있다는 지적에 의해 증가 될 수 ObjectWriterObjectReader개체에 의해 구성 할 수있다 ObjectMapper. 그것들은 완전히 불변이고 스레드 안전합니다. 이는 이론적으로 스레드 안전 문제 ( ObjectMapper코드가 인스턴스를 재구성하려고 할 때 발생할 수 있음)를 일으킬 수 없다는 것을 의미합니다 .


ObjectMapper는 스레드 안전하지만 특히 다중 스레드 응용 프로그램에서 정적 변수로 선언하지 않는 것이 좋습니다. 나쁜 습관이 아니라 교착 상태의 위험이 높기 때문에. 나는 내 자신의 경험에서 그것을 말하고 있습니다. 웹 서비스에서 JSON 데이터를 가져오고 처리하는 4 개의 동일한 스레드로 응용 프로그램을 만들었습니다. 스레드 덤프에 따라 내 응용 프로그램이 다음 명령에서 자주 중단되었습니다.

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

그 외에도 성능이 좋지 않았습니다. 정적 변수를 인스턴스 기반 변수로 바꾸면 정지가 사라지고 성능이 4 배가되었습니다. 즉, 240 만 개의 JSON 문서가 2.5 시간이 아닌 40 분 56 초 동안 처리되었습니다.


스레드 안전성 측면에서 정적 ObjectMapper를 선언하는 것이 안전하지만 Java에서 정적 Object 변수를 구성하는 것은 나쁜 습관으로 간주됩니다. 자세한 내용 은 정적 변수가 악의로 간주되는 이유를 참조하십시오 . (원하는 경우 내 대답 )

요컨대, 간결한 단위 테스트를 작성하기 어렵 기 때문에 정적을 피해야합니다. 예를 들어 정적 최종 ObjectMapper를 사용하면 더미 코드 또는 no-op에 대한 JSON 직렬화를 교체 할 수 없습니다.

또한 정적 파이널을 사용하면 런타임에 ObjectMapper를 다시 구성 할 수 없습니다. 당신은 지금 그 이유를 구상하지 못할 수도 있지만, 정적 최종 패턴에 자신을 고정시키는 경우, 클래스 로더를 분해하여 다시 초기화 할 수는 없습니다.

ObjectMapper의 경우는 좋지만 일반적으로 나쁜 습관이며 오래 지속되는 객체를 관리하기 위해 싱글 톤 패턴 또는 제어 역전을 사용하는 것보다 이점이 없습니다.


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

저자에게 신용.


com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)

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)

클래스 com.fasterxml.jackson.databind.type.TypeFactory의 _hashMapSuperInterfaceChain 메소드 가 동기화되었습니다. 높은 부하에서 동일한 경합이 발생합니다.

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

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



반응형