IT story

단순한 1L 대신 긴 serialVersionUID를 생성하는 이유는 무엇입니까?

hot-time 2020. 5. 7. 08:00
반응형

단순한 1L 대신 긴 serialVersionUID를 생성하는 이유는 무엇입니까?


클래스가 Eclipse에서 Serializable을 구현할 때 add default serialVersionUID(1L)또는 generated 옵션이 있습니다 serialVersionUID(3567653491060394677L). 나는 첫 번째 것이 더 시원하다고 생각하지만, 두 번째 옵션을 사용하는 사람들을 여러 번 보았습니다. 생성 할 이유가 long serialVersionUID있습니까?


내가 알 수있는 한, 그것은 이전 릴리스와의 호환성을위한 것입니다. 이것은 이전에 serialVersionUID 사용을 무시한 다음 호환 가능 해야 하지만 직렬화가 중단 되도록 변경 한 경우에만 유용합니다 .

자세한 내용은 Java Serialization Spec 을 참조하십시오.


직렬화 버전 UID의 목적은 객체의 유효한 직렬화를 수행하기 위해 클래스의 다른 버전을 추적하는 것입니다.

아이디어는 클래스의 특정 버전에 고유 한 ID를 생성하는 것이며, 이는 직렬화 된 객체의 구조에 영향을주는 새 필드와 같이 클래스에 추가 된 새로운 세부 사항이있을 때 변경됩니다.

1L미래에 클래스 정의가 변경되어 직렬화 된 객체의 구조가 변경되면 객체를 직렬화 해제하려고 할 때 문제가 발생할 가능성이 있음 의미하는 것과 같은 항상 동일한 ID를 사용하십시오 .

ID가 생략되면 Java는 실제로 객체의 필드를 기반으로 ID를 계산하지만 비싼 프로세스이므로 수동으로 제공하면 성능이 향상됩니다.

다음은 클래스의 직렬화 및 버전 관리에 대해 설명하는 기사 링크입니다.


생성 된 것의 주된 이유는 이미 사본을 보유한 기존 버전의 클래스와 호환되도록하기 위해서입니다.


의 "long"기본값은 기본 직렬화 동작에서 계산 된 Java Serialization Specification에serialVersionUID 정의 된 기본값입니다.

따라서 기본 버전 번호를 추가하면 구조적으로 변경된 것이없는 한 클래스의 직렬화가 더 디 직렬화되지만 클래스를 변경하면 (필드 추가 / 제거) 클래스를 업데이트해야합니다. 일련 번호.

기존 비트 스트림과 호환되지 않아도되는 1L경우 변경 사항이있을 때 필요에 따라 버전을 추가하고 버전을 늘릴 수 있습니다. 즉, 변경된 클래스의 기본 직렬화 버전이 이전 클래스의 기본 버전과 다른 경우입니다.


구현하는 클래스를 정의 할 때마다 반드시 serialVersionUID를 작성해야합니다 java.io.Serializable. 그렇지 않으면 자동으로 생성되지만 이것은 나쁘다. 자동 생성 된 serialVersionUID는 클래스의 메서드 서명을 기반으로하므로 나중에 클래스를 변경하여 메서드를 추가하면 (예 :) "이전"버전의 클래스를 직렬화 해제하는 데 실패합니다. 일어날 수있는 일은 다음과 같습니다.

  1. serialVersionUID를 정의하지 않고 클래스의 첫 번째 버전을 만듭니다.
  2. 클래스의 인스턴스를 영구 저장소로 직렬화하십시오. serialVersionUID가 자동으로 생성됩니다.
  3. 클래스를 수정하여 새 메소드를 추가하고 애플리케이션을 재배치하십시오.
  4. 2 단계에서 직렬화 된 인스턴스를 직렬화 해제하려고 시도하지만 자동 생성 된 serialVersionUID가 다르기 때문에 이제는 실패합니다 (성공해야 할 경우).

serialVersionUID를 지정하지 않으면 Java가 즉시 작성합니다. 생성 된 serialVersionUID는 해당 번호입니다. 클래스에서 이전의 직렬화 된 버전과 호환되지 않지만 해시를 변경하는 것을 변경하는 경우 생성 된 매우 큰 serialVersionUID (또는 오류 메시지의 "예상"번호)를 사용해야합니다 . 그렇지 않으면 모든 것을 스스로 추적하는 경우 0, 1, 2 ...가 더 좋습니다.


serialVersionUID (3567653491060394677L)를 생성하는 대신 serialVersionUID (1L)를 사용하면 무언가를 말하는 것입니다.

이 클래스의 버전 번호 1과 호환되지 않는이 클래스의 직렬화 된 버전을 가진이 클래스를 다루는 시스템이 없다고 100 % 확신한다고 말하고 있습니다.

직렬화 된 버전 기록이 알려지지 않았다는 변명을 생각할 수 있다면 자신감을 가지고 말하기가 어려울 수 있습니다. 평생 동안 성공적인 수업은 많은 사람들에 의해 유지되고 많은 프로젝트에 살고 많은 시스템에 상주 할 것입니다.

당신은 그것을 고민 할 수 있습니다. 또는 당신은 잃고 싶어 복권을 재생할 수 있습니다. 버전을 생성하면 문제가 발생할 가능성이 거의 없습니다. "아직 아무도 1을 사용하지 않았다"고 가정하면 확률은 작은 것보다 큽니다. 우리 모두가 0과 1이 멋지다고 생각하기 때문입니다.

-

serialVersionUID (1L)를 사용하지 않고 serialVersionUID (3567653491060394677L)를 생성하면 무언가를 말하는 것입니다.

사람들 이이 클래스의 역사에서 다른 버전 번호를 수동으로 만들거나 생성했을 수 있으며 Longs가 큰 숫자이기 때문에 걱정하지 않아도됩니다.

어떤 방식 으로든 클래스가 존재하거나 존재하는 전체 유니버스에서 클래스를 직렬화 할 때 사용 된 버전 번호 기록을 완벽하게 알지 못하면 기회가 있습니다. 1이 AOK인지 100 % 확신 할 시간이 있다면 그것을 찾으십시오. 그것이 많은 일이라면, 계속해서 맹목적으로 숫자를 생성하십시오. 복권 당첨 가능성이 더 높습니다. 그렇다면, 알려주세요. 맥주를 사겠습니다.

추첨에 대한이 모든 이야기를 통해 serialVersionUID가 무작위로 생성된다는 인상을 받았을 것입니다. 실제로 숫자 범위가 Long의 가능한 모든 값에 균등하게 분배되는 한 괜찮습니다. 그러나 실제로는 다음과 같이 수행됩니다.

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100

The only difference you get with that is you don't need a source of random. You're using the changes in class itself to change the result. But according to the pigeonhole principle there is still a chance it could go wrong and have a collision. It's just incredibly unlikely. So good luck getting a beer out of me.

However, even if the class will only ever live in one system and one code base, thinking that incrementing the number by hand gives you zero chance of collisions just means you don't understand humans. :)


Well, serialVersionUID is an exception to the rule that “static fields don’t get serialized”. ObjectOutputStream writes every time the value of serialVersionUID to the output stream. ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException. Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.


Because in many cases default id is not unique. so we create id for making unique concept.


To add to @David Schmitts answer, as a rule of thumb I would always use the default 1L out of convention. I've only had to go back and change some of them a few times, but I knew that when I made the change and updated the default number by one each time.

At my current company they require the auto-generated number so I use that for convention, but I prefer the default. My take is, if it's not a convention where you work, use the default, unless you think you will be constantly changing the structure of you serialized classes for some reason.

참고URL : https://stackoverflow.com/questions/888335/why-generate-long-serialversionuid-instead-of-a-simple-1l

반응형