Co to jest serialVersionUID i dlaczego powinienem go używać?

Eclipse wyświetla ostrzeżenia, gdy brakuje serialVersionUID.

Klasa serializowalna Foo nie deklaruje statycznego finału serialVersionUID pole typu long

Czym jest serialVersionUID i dlaczego jest to ważne? Proszę pokazać przykład, w którym brak serialVersionUID spowoduje problem.

Author: jmj, 2008-11-12

26 answers

Docs for java.io.Serializable są chyba równie dobre wytłumaczenie jak dostaniesz:

Środowisko uruchomieniowe serializacji kojarzy z każdą klasą serializowalną numer wersji a, zwany serialVersionUID, który jest używany podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca serializowanego obiektu mają załadowane klasy dla tego obiektu, które są zgodne z serializacją. Jeśli odbiornik załadował klasę dla obiektu, który ma inną serialVersionUID niż odpowiedniej klasy nadawcy, wówczas deserializacja spowoduje InvalidClassException. Klasa serializowalna może zadeklarować własne serialVersionUID jawnie, deklarując pole o nazwie serialVersionUID, które musi być statyczne, końcowe i typu long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

Jeśli Klasa serializowalna nie deklaruje jawnie serialVersionUID, to środowisko uruchomieniowe serializacji obliczy domyślną wartość serialVersionUID dla tej klasy na podstawie różnych aspektów klasy, jak opisano w obiekcie Java(TM) Specyfikacja Serializacji. Jednak jest zdecydowanie zalecane, aby wszystkie klasy serializowalne jawnie deklarowały serialVersionUID wartości, ponieważ domyślne obliczenia serialVersionUID są bardzo wrażliwe na szczegóły klas, które mogą się różnić w zależności od implementacji kompilatora, a tym samym mogą spowodować nieoczekiwane InvalidClassExceptions podczas deserializacji. Dlatego, aby zagwarantować spójną wartość serialVersionUID w różnych implementacjach kompilatora java, Klasa serializowalna musi zadeklarować jawną wartość serialVersionUID. Jest to również zdecydowanie zaleca się, aby jawne deklaracje serialVersionUID używały modyfikatora prywatnego tam, gdzie to możliwe, ponieważ takie deklaracje dotyczą tylko bezpośrednio deklarującej klasy-pola serialVersionUID nie są użyteczne jako dziedziczone elementy.

 2384
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-14 19:54:54

Jeśli serializujesz tylko dlatego, że musisz serializować ze względu na implementację (kogo obchodzi, czy serializujesz dla HTTPSession, Na przykład...jeśli jest przechowywany lub nie, prawdopodobnie nie zależy ci na de-serializing obiekcie formularza), możesz to zignorować.

Jeśli faktycznie używasz serializacji, ma to znaczenie tylko wtedy, gdy planujesz przechowywać i pobierać obiekty bezpośrednio przy użyciu serializacji. serialVersionUID reprezentuje Twoją wersję klasową i powinieneś ją zwiększyć, jeśli bieżąca wersja twojego klasa nie jest wstecznie kompatybilna ze swoją poprzednią wersją.

Przez większość czasu prawdopodobnie nie będziesz używać serializacji bezpośrednio. Jeśli tak jest, Wygeneruj domyślną SerialVersionUID, klikając opcję quick fix i nie martw się o to.

 491
Author: MetroidFan2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-24 07:17:24

Nie mogę przepuścić tej okazji, aby podłączyć książkę Josha Blocha Effective Java (2nd Edition). Rozdział 11 jest niezbędnym źródłem informacji na temat serializacji Javy.

Dla Josha, automatycznie generowany UID jest generowany na podstawie nazwy klasy, zaimplementowanych interfejsów oraz wszystkich publicznych i chronionych członków. Zmiana któregokolwiek z nich w jakikolwiek sposób zmieni serialVersionUID. Więc nie musisz z nimi zadzierać tylko wtedy, gdy jesteś pewien, że nie więcej niż jedna wersja klasy kiedykolwiek będzie serializowane (w różnych procesach lub pobrane z magazynu w późniejszym czasie).

Jeśli je teraz zignorujesz, a później okaże się, że musisz zmienić klasę w jakiś sposób, ale zachować kompatybilność ze starą wersją klasy, możesz użyć narzędzia JDK serialver do wygenerowania serialVersionUID Na starej klasie i jawnie ustawić ją na nowej klasie. (W zależności od zmian może być również konieczne zaimplementowanie niestandardowej serializacji poprzez dodanie metod writeObject i readObject - patrz Serializable javadoc lub wspomniany Rozdział 11.)

 319
Author: Scott Bale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 13:32:35

Możesz powiedzieć Eclipse, aby zignorował Ostrzeżenia serialVersionUID:

Okno > Preferencje > Java > Kompilator > Błędy / Ostrzeżenia > Potencjalne Problemy Z Programowaniem

Jeśli nie wiesz, istnieje wiele innych ostrzeżeń, które możesz włączyć w tej sekcji (lub nawet mieć niektóre zgłoszone jako błędy), wiele z nich jest bardzo przydatnych:

  • potencjalne problemy z programowaniem: możliwe przypadkowe przypisanie logiczne
  • potencjalne problemy z programowaniem: wskaźnik Null access
  • niepotrzebny kod: zmienna lokalna nigdy nie jest odczytywana
  • niepotrzebny kod: zbędne sprawdzanie null
  • niepotrzebny kod: niepotrzebny cast lub 'instanceof'

I wiele innych.

 140
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-13 01:17:00

serialVersionUID ułatwia wersjonowanie serializowanych danych. Jego wartość jest zapisywana wraz z danymi podczas serializacji. Podczas usuwania serializacji sprawdzana jest ta sama wersja, aby sprawdzić, jak dane serializowane pasują do bieżącego kodu.

Jeśli chcesz zmodyfikować swoje dane, zwykle zaczynasz od serialVersionUID z 0 i przy każdej zmianie strukturalnej przenosisz je do klasy, która zmienia serializowane dane (dodawanie lub usuwanie nie-przejściowych pól).

Wbudowany mechanizm de-serializacji (in.defaultReadObject()) będzie odmówić usunięcia serializacji ze starych wersji danych. Ale jeśli chcesz, możesz zdefiniować własną readObject () -funkcję, która może odczytywać stare dane. Ten niestandardowy kod może następnie sprawdzić serialVersionUID, aby dowiedzieć się, w której wersji znajdują się Dane i zdecydować, jak je usunąć. Ta technika wersjonowania jest przydatna, jeśli przechowujesz dane seryjne, które przetrwają kilka wersji kodu.

Ale przechowywanie serializowanych danych przez tak długi czas nie jest zbyt powszechne. To znacznie więcej często używa się mechanizmu serializacji do tymczasowego zapisu danych na przykład do pamięci podręcznej lub wysyłania ich przez sieć do innego programu z tą samą wersją odpowiednich części kodu.

W tym przypadku nie jesteś zainteresowany utrzymaniem wstecznej kompatybilności. Zależy Ci tylko na upewnieniu się, że bazy kodu, które się komunikują, rzeczywiście mają te same wersje odpowiednich klas. Aby ułatwić taką kontrolę, należy zachować serialVersionUID tak jak przed i nie zapomnij zaktualizować go podczas dokonywania zmian w klasach.

Jeśli zapomnisz zaktualizować pole, możesz skończyć z dwiema różnymi wersjami klasy o innej strukturze, ale z tą samą serialVersionUID. Jeśli tak się stanie, domyślny mechanizm (in.defaultReadObject()) nie wykryje żadnej różnicy i spróbuje usunąć serializację niezgodnych danych. Teraz możesz skończyć z tajemniczym błędem uruchomieniowym lub cichą awarią (pola null). Tego typu błędy mogą być trudne do znalezienia.

Tak aby pomoc w tym usecase, Platforma Java oferuje wybór nie ustawiania serialVersionUID ręcznie. Zamiast tego, hash struktury klasy zostanie wygenerowany w czasie kompilacji i użyty jako id. Ten mechanizm upewni się, że nigdy nie masz różnych struktur klas o tym samym id, a więc nie otrzymasz tych trudnych do wyśledzenia błędów serializacji runtime, o których mowa powyżej.

Ale jest zaplecze automatycznej strategii id. Mianowicie, że wygenerowane identyfikatory dla tej samej klasy mogą różnią się między kompilatorami (jak wspomniał wcześniej Jon Skeet). Jeśli więc przekazujesz dane seryjne między kodami skompilowanymi za pomocą różnych kompilatorów, zaleca się ręczne utrzymywanie identyfikatorów.

A jeśli jesteś wstecznie kompatybilny ze swoimi danymi, jak w pierwszym przypadku użycia, prawdopodobnie chcesz również zachować identyfikator samodzielnie. Aby uzyskać czytelne identyfikatory i mieć większą kontrolę nad tym, kiedy i jak się zmieniają.

 117
Author: Alexander Torstling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-03 06:20:58

Co to jest serialVersionUID i dlaczego powinienem go używać?

SerialVersionUID jest unikalnym identyfikatorem dla każdej klasy, JVM używa go do porównania wersji klasy, zapewniając, że ta sama klasa została użyta podczas serializacji jest ładowana podczas deserializacji.

Podanie jednego daje większą kontrolę, chociaż JVM generuje jeden, jeśli nie podasz. Wygenerowana wartość może się różnić w zależności od kompilatora. Ponadto, czasami po prostu chcesz z jakiegoś powodu zabronić deserializacji starych serializowanych obiektów [backward incompatibility], a w tym przypadku wystarczy zmienić serialVersionUID.

Javadocs dla Serializable powiedz :

Domyślne obliczenia serialVersionUID są bardzo wrażliwe na klasę szczegóły, które mogą się różnić w zależności od implementacji kompilatora i mogą w ten sposób powstają nieoczekiwane InvalidClassExceptions podczas deserializacja.

Dlatego musisz zadeklarować serialVersionUID, ponieważ daje nam więcej kontrola .

Ten artykuł ma kilka dobrych punktów na ten temat.

 75
Author: Thalaivar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 07:03:56

Pierwotne pytanie zadało pytanie "dlaczego jest to ważne" i "przykład", gdzie to Serial Version ID byłoby przydatne. Znalazłem.

Powiedzmy, że tworzysz klasę Car, tworzysz jej instancję i zapisujesz ją do strumienia obiektów. Spłaszczony obiekt car znajduje się przez pewien czas w systemie plików. W międzyczasie, jeśli klasa Car zostanie zmodyfikowana przez dodanie nowego pola. Później, gdy spróbujesz odczytać (np. deserializować) spłaszczony obiekt Car, otrzymasz java.io.InvalidClassException - ponieważ wszystkie klasy serializowalne są automatycznie otrzymuje unikalny identyfikator. Wyjątek ten jest wyrzucany, gdy identyfikator klasy nie jest równy identyfikatorowi spłaszczonego obiektu. Jeśli naprawdę się nad tym zastanowić, wyjątek jest wyrzucany z powodu dodania nowego pola. Możesz uniknąć rzucania tego wyjątku poprzez samodzielne kontrolowanie wersji poprzez zadeklarowanie jawnego identyfikatora serialVersionUID. Istnieje również niewielka korzyść z wydajności w jawnym deklarowaniu serialVersionUID (ponieważ nie musi być obliczana). Więc, najlepiej jest dodać własne serialVersionUID do klas Serializowalnych, gdy tylko je utworzysz, jak pokazano poniżej:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}
 59
Author: Rupesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-14 14:56:35

Najpierw muszę wyjaśnić, czym jest serializacja.

Serializacja pozwala na konwersję obiektu do strumienia, aby wysłać ten obiekt przez sieć lub zapisać do pliku lub zapisać do DB dla użycia liter.

istnieją pewne zasady serializacji.

  • Obiekt jest serializowalny tylko wtedy, gdy jego klasa lub klasa nadrzędna implementuje interfejs Serializowalny

  • Obiekt jest serializowalny (sam implementuje Serializowalny interfejs), nawet jeśli jego superklasa nie jest Jednak pierwsza klasa w hierarchii klasy serializowalnej, która nie implementuje interfejsu Serializowalnego, musi mieć konstruktor no-arg. Jeśli zostanie to naruszone, readObject () wytworzy obiekt java.io.InvalidClassException w środowisku runtime

  • Wszystkie prymitywne typy są serializowalne.

  • Pola przejściowe (z modyfikatorem przejściowym) nie są serializowane (tzn. nie są zapisywane ani przywracane). A Klasa implementacja Serializowalna musi oznaczać przejściowe pola klas, które nie obsługują serializacji (np. strumień plików).

  • Pola statyczne (z modyfikatorem statycznym) nie są serializowane.

Gdy Object jest serializowana, środowisko Java Runtime kojarzy numer wersji seryjnej aka, serialVersionID.

gdzie potrzebujemy serialVersionID:

Podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca są zgodne w odniesieniu do serializacja. Jeśli odbiornik załadował klasę inną serialVersionID, deserializacja zakończy się InvalidClassCastException.
Klasa serializowalna może zadeklarować swoją własną serialVersionUID jawnie, deklarując pole o nazwie serialVersionUID, które musi być statyczne, końcowe i typu long.

Spróbujmy na przykładzie.

import java.io.Serializable;

public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private String empname;
    private byte empage;

    public String getEmpName() {
        return name;
    }

    public void setEmpName(String empname) {
        this.empname = empname;
    }

    public byte getEmpAge() {
        return empage;
    }

    public void setEmpAge(byte empage) {
        this.empage = empage;
    }

    public String whoIsThis() {
        return getEmpName() + " is " + getEmpAge() + "years old";
    }
}

Utwórz Obiekt Serialize

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Writer {
    public static void main(String[] args) throws IOException {
        Employee employee = new Employee();
        employee.setEmpName("Jagdish");
        employee.setEmpAge((byte) 30);

        FileOutputStream fout = new
                FileOutputStream("/users/Jagdish.vala/employee.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(employee);
        oos.close();
        System.out.println("Process complete");
    }
}

Deserializuj obiekt

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Reader {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        Employee employee = new Employee();
        FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj");
        ObjectInputStream ois = new ObjectInputStream(fin);
        employee = (Employee) ois.readObject();
        ois.close();
        System.out.println(employee.whoIsThis());
    }
}

Uwaga: teraz Zmień identyfikator serialVersionUID klasy pracownika i zapisz:

private static final long serialVersionUID = 4L;

I Uruchom klasę Reader. Nie wykonaj klasy Writer, a otrzymasz wyjątek.

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)
 50
Author: JegsVala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-22 10:46:07

Jeśli nigdy nie będziesz musiał serializować swoich obiektów do tablicy bajtów i wysyłać/przechowywać ich, nie musisz się tym martwić. Jeśli to zrobisz, musisz wziąć pod uwagę identyfikator serialVersionUID, ponieważ deserializer obiektu dopasuje go do wersji obiektu, którą posiada jego classloader. Więcej na ten temat można przeczytać w specyfikacji języka Java.

 39
Author: eishay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-09 18:46:25

Jeśli dostajesz to Ostrzeżenie NA klasie, o której nigdy nie myślisz serializując, i że nie deklarujesz się implements Serializable, to często dlatego, że odziedziczyłeś po superklasie, który implementuje Serializowalny. Często wtedy lepiej byłoby delegować do takiego obiektu zamiast używać dziedziczenia.

Więc zamiast

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

Do

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

I w odpowiednich metodach wywołaj myList.foo() zamiast this.foo() (lub super.foo()). (Nie pasuje to we wszystkich przypadkach, ale nadal całkiem często.)

Często widzę ludzi rozszerzających JFrame lub takie, kiedy naprawdę muszą tylko delegować do tego. (Pomaga to również w automatycznym uzupełnianiu w IDE, ponieważ JFrame ma setki metod, których nie potrzebujesz, gdy chcesz wywołać niestandardowe metody na swojej klasie.)

Jednym z przypadków, w którym ostrzeżenie (lub serialVersionUID) jest nieuniknione, jest rozszerzenie z AbstractAction, zwykle w anonimowej klasie, dodając tylko metodę actionPerformed. Myślę, że nie powinno być ostrzeżenie w tym przypadku (ponieważ normalnie nie można niezawodnie serializować i deserializować takich anonimowych klas i tak accross różnych wersji klasy), ale nie jestem pewien, jak kompilator może to rozpoznać.

 34
Author: Paŭlo Ebermann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-03 00:32:03

Aby zrozumieć znaczenie field serialVersionUID, należy zrozumieć, jak działa serializacja/Deserializacja.

Gdy obiekt klasy Serializowalny jest serializowany Java Runtime kojarzy wersję szeregową nr.(nazywany serialVersionUID) z tym serializowanym obiektem. W momencie deserializacji tego serializowanego obiektu środowisko Java Runtime dopasowuje identyfikator serialVersionUID obiektu serializowanego do identyfikatora serialVersionUID klasy. Jeśli oba są równe, to tylko z dalszy proces deserializacji else rzuca InvalidClassException.

Wnioskujemy więc, że aby proces serializacji/deserializacji zakończył się sukcesem, serialVersionUID obiektu serializowanego musi być równoważny serialVersionUID klasy. W przypadku, gdy programista jawnie określi w programie wartość serialVersionUID, to ta sama wartość będzie powiązana z serializowanym obiektem i klasą, niezależnie od platformy serializacji i deserializacji(np. serializacja może być wykonywana na platformach takich jak windows za pomocą sun lub MS JVM, a Deserializacja może być na innej platformie Linux za pomocą Zing JVM).

Ale w przypadku, gdy serialVersionUID nie jest określony przez programistę, to podczas wykonywania Serialization\DeSerialization dowolnego obiektu, Java runtime używa własnego algorytmu do jego obliczenia. Ten algorytm obliczania serialVersionUID różni się w zależności od JRE. Możliwe jest również, że środowisko, w którym obiekt jest serializowany, wykorzystuje jednym JRE (np. SUN JVM) i środowiskiem, w którym następuje deserializacja, jest Linux Jvm(Zing). W takich przypadkach serialVersionUID skojarzony z serialized object będzie inny niż serialVersionUID klasy obliczonej w środowisku deserialzation. Z kolei deserializacja nie zakończy się sukcesem. Aby uniknąć takich sytuacji/problemów programista musi zawsze podać serialVersionUID klasy Serializable.

 22
Author: Nitesh Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 21:34:52

Jako przykład, w którym brakujący identyfikator serialVersionUID może spowodować problem:

Pracuję nad tą aplikacją Java EE, która składa się z modułu WWW, który używa modułu EJB. Moduł web wywołuje moduł EJB zdalnie i przekazuje POJO, który implementuje Serializable jako argument.

Ta klasa POJO's została zapakowana wewnątrz jar EJB i wewnątrz własnego jar w WEB-INF/lib modułu web. To faktycznie ta sama klasa, ale kiedy pakuję moduł EJB rozpakowuję ten słoik POJO do pakowania go razem z modułem EJB.

Wywołanie do EJB nie powiodło się z wyjątkiem poniżej, ponieważ nie zadeklarowałem jego serialVersionUID:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52
 20
Author: Henrique Ordine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 18:15:18

Nie przejmuj się, domyślne obliczenia są naprawdę dobre i wystarczają na 99,9999% przypadków. A jeśli napotkasz problemy, możesz - Jak już wspomniano-wprowadzić UID jako need arrise (co jest bardzo mało prawdopodobne)

 17
Author: grand johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 15:59:41

Zazwyczaj używam serialVersionUID w jednym kontekście: kiedy Wiem, że będzie opuszczać kontekst maszyny wirtualnej Java.

Wiedziałbym o tym, kiedy używam ObjectInputStream i ObjectOutputStream dla mojej aplikacji lub jeśli znam bibliotekę/framework, którego używam, użyję go. SerialVersionID zapewnia, że różne maszyny wirtualne Java różnych wersji lub dostawców będą działać poprawnie lub jeśli są przechowywane i pobierane poza maszyną wirtualną, na przykład HttpSession Dane sesji mogą pozostać nawet podczas ponownego uruchomienia i aktualizacji aplikacji serwer.

Do wszystkich innych przypadków używam

@SuppressWarnings("serial")

Ponieważ przez większość czasu domyślna serialVersionUID jest wystarczająca. Obejmuje to Exception, HttpServlet.

 16
Author: Archimedes Trajano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 16:17:48

Pole data reprezentuje niektóre informacje przechowywane w klasie. Class implementuje interfejs Serializable, więc eclipse automatycznie zaoferowało zadeklarowanie pola serialVersionUID. Zacznijmy od wartości 1 ustawionej tam.

Jeśli nie chcesz, aby to Ostrzeżenie przyszło, użyj tego:

@SuppressWarnings("serial")
 14
Author: Mukti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 14:54:36

Byłoby miło, gdyby CheckStyle mógł sprawdzić, czy serialVersionUID na klasie implementującej Serializable ma dobrą wartość, tzn. że pasuje do tego, co wygeneruje Generator ID wersji seryjnej. Jeśli masz projekt z dużą ilością serializowalnych DTOs, na przykład, pamiętając o usunięciu istniejącego serialVersionUID i regeneracji jest to ból, a obecnie jedynym sposobem (o którym wiem), Aby to zweryfikować, jest regeneracja dla każdej klasy i porównanie do starej. To jest bardzo bolesne.

 11
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-03 14:44:33

SerialVersionUID służy do kontroli wersji obiektu. możesz również określić serialVersionUID w pliku klasy. Konsekwencją niepodania serialVersionUID jest to, że gdy dodasz lub zmodyfikujesz dowolne pole w klasie, wtedy już serializowana klasa nie będzie w stanie odzyskać, ponieważ serialVersionUID wygenerowany dla nowej klasy i dla starego serializowanego obiektu będzie inny. Proces serializacji w Javie polega na prawidłowym identyfikatorze serialVersionUID do odzyskiwania stanu serializowanych obiektów i rzutów java. io. InvalidClassException w przypadku niezgodności serialVersionUID

Czytaj więcej: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ

 11
Author: Coder123,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 21:08:11

Po co używać SerialVersionUID wewnątrz Serializable klasy w Javie?

Podczas serialization Java runtime tworzy numer wersji dla klasy, aby później mogła ją zdeserializować. Ten numer wersji jest znany jako SerialVersionUID w języku Java.

SerialVersionUID służy do wersji serializowanych danych. Możesz usunąć serializację klasy tylko wtedy, gdy SerialVersionUID pasuje do serializowanej instancji. Kiedy nie deklarujemy SerialVersionUID w naszej klasie, Java runtime generuje ją dla nas, ale nie jest zalecana. Zaleca się deklarowanie SerialVersionUID jako zmienna private static final long, aby uniknąć domyślnego mechanizmu.

Gdy deklarujesz klasę jako {[1] } implementując interfejs znacznika java.io.Serializable, instancja Java runtime persist tej klasy jest zapisywana na dysk przy użyciu domyślnego mechanizmu serializacji, o ile nie dostosowano procesu za pomocą interfejsu Externalizable.

Zobacz także Po co używać SerialVersionUID wewnątrz klasy Serializable w Javie

 10
Author: roottraveller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-05 03:37:55

Jeśli chcesz zmienić ogromną liczbę klas, które nie miały ustawionego identyfikatora serialVersionUID, zachowując kompatybilność ze starymi klasami, narzędzia takie jak IntelliJ Idea, Eclipse zawodzą, ponieważ generują losowe liczby i nie działają na kilku plikach za jednym zamachem. I wymyślić następujący skrypt bash (przykro Mi dla użytkowników Windows, rozważyć zakup Mac lub konwertować na Linux), aby zmienić serialVersionUID problem z łatwością:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               

while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

Zapisujesz ten skrypt, powiedzmy add_serialVersionUID.sh do ciebie ~ / bin. Następnie uruchom go w katalogu głównym Twojego projektu Maven lub Gradle:

add_serialVersionUID.sh < myJavaToAmend.lst
To .lst zawiera listę plików java do dodania identyfikatora serialVersionUID w następującym formacie:
com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

Ten skrypt używa narzędzia JDK serialVer pod maską. Upewnij się więc, że twój $JAVA_HOME / bin znajduje się w ścieżce.

 8
Author: schnell18,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-27 12:36:07

To pytanie jest bardzo dobrze udokumentowane w efektywnej Javie przez Joshuę Blocha. Bardzo dobra książka i lektura obowiązkowa. Poniżej przedstawię niektóre z powodów:

Środowisko uruchomieniowe serializacji zawiera numer o nazwie Wersja szeregowa dla każdej klasy serializowalnej. Numer ten nazywa się serialVersionUID. Teraz za tą liczbą kryje się trochę matematyki i wychodzi ona na podstawie pól / metod zdefiniowanych w klasie. Dla tej samej klasy za każdym razem generowana jest ta sama wersja. Ten numer jest używany podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca serializowanego obiektu mają załadowane klasy dla tego obiektu, które są zgodne w odniesieniu do serializacji. Jeśli odbiorca załadował klasę dla obiektu, który ma inny identyfikator serialVersionUID niż odpowiednia Klasa nadawcy, deserializacja spowoduje wyjątek InvalidClassException.

Jeśli klasa jest serializowalna, możesz również zadeklarować swój własny serialVersionUID jawnie deklarując pole nazwany "serialVersionUID", który musi być statyczny, końcowy i typu long. Większość IDE jest jak Eclipse pomóc wygenerować ten długi ciąg.

 6
Author: Geek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-03 19:41:31

Za każdym razem, gdy obiekt jest serializowany, obiekt jest stemplowany numerem ID wersji dla klasy obiektu.Ten identyfikator nazywa się serialVersionUID i jest obliczany na podstawie informacji o strukturze klasy. Załóżmy, że stworzyłeś klasę pracowniczą i ma ona ID wersji # 333 (przypisany przez JVM), teraz, kiedy będziesz serializował obiekt tej klasy (Załóżmy, że obiekt pracowniczy), JVM przypisze mu UID jako #333.

Zastanów się nad sytuacją - w przyszłości musisz edytować lub zmienić swoje klasa i w takim przypadku, gdy ją zmodyfikujesz, JVM przypisze jej nowy UID (Załóżmy #444). Teraz, gdy próbujesz deserializować obiekt pracowniczy, JVM porównuje identyfikator wersji obiektu serialized (obiekt pracowniczy) (#333) z identyfikatorem klasy i.e #444(ponieważ został zmieniony). Dla porównania JVM stwierdzi, że obie wersje UID są różne i dlatego Deserializacja nie powiedzie się. Stąd jeśli serialVersionID dla każdej klasy jest zdefiniowany przez samego programistę. Będzie tak samo, nawet jeśli w przyszłości Klasa zostanie rozwinięta i dlatego JVM zawsze stwierdzi, że klasa jest zgodna z serializowanym obiektem, nawet jeśli klasa zostanie zmieniona. Więcej informacji można znaleźć w rozdziale 14 HEAD FIRST JAVA.

 6
Author: Naved Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Proste Wyjaśnienie:

  1. Czy serializujesz dane? Serializacja to w zasadzie zapisanie danych klas do pliku / strumienia / etc. De-serializacja to odczyt tych danych z powrotem do klasy.
  2. Czy zamierzasz wejść do produkcji?

    Jeśli po prostu testujesz coś z nieistotnymi / fałszywymi danymi, nie martw się o to (chyba że testujesz serializację bezpośrednio).

  3. Czy to pierwsza wersja?

    Jeśli tak, ustaw serialVersionUID=1L.

  4. Czy to drugi, trzeci itd. wersja prod?

    Teraz musisz się martwić serialVersionUID i przyjrzeć się temu dogłębnie.

Zasadniczo, jeśli nie zaktualizujesz poprawnie wersji podczas aktualizacji klasy, którą musisz zapisać/przeczytać, pojawi się błąd podczas próby odczytania starych danych.

 3
Author: gagarwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-12 13:44:29

'serialVersionUID' jest 64-bitowym numerem używanym do jednoznacznej identyfikacji klasy podczas procesu deserializacji. Podczas serializacji obiektu, serialVersionUID klasy również jest zapisywany do pliku. Za każdym razem, gdy deserializujesz ten obiekt, java run time wyodrębnia tę wartość serialVersionUID z danych serializowanych i porównuje tę samą wartość powiązaną z klasą. Jeśli oba nie pasują do siebie, to zostanie wyrzucone 'java.io.InvalidClassException'.

Jeśli Klasa serializowalna nie deklaruje jawnie serialVersionUID, a następnie serialization runtime obliczy wartość serialVersionUID dla tej klasy na podstawie różnych aspektów klasy, takich jak pola, metody itp.,, Możesz odwołać się do tego link dla aplikacji demo.

 3
Author: Hari Krishna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-20 15:14:59

Aby opowiedzieć długą historię, pole to służy do sprawdzenia, czy serializowane dane mogą być poprawnie deserializowane. Serializacja i deserializacja są często wykonywane przez różne kopie programu - na przykład serwer konwertuje obiekt na ciąg znaków, a Klient konwertuje odebrany ciąg znaków na obiekt. Pole to mówi, że oba działają z tym samym wyobrażeniem o tym, czym jest ten obiekt. To pole pomaga, gdy:

  • Masz wiele różnych kopii programu w różnych miejscach (np. 1 serwer i 100 klientów). Jeśli zmienisz swój obiekt, zmienisz numer wersji i zapomnisz zaktualizować jednego z klientów, będzie wiedział, że nie jest on w stanie deserializacji

  • Przechowałeś swoje dane w jakimś pliku i Później próbujesz go otworzyć za pomocą zaktualizowanej wersji programu ze zmodyfikowanym obiektem-będziesz wiedział, że ten plik nie jest kompatybilny jeśli zachowasz poprawną wersję

Kiedy jest to ważne?

Najbardziej oczywiste - jeśli dodasz kilka pól do swojego obiekt, starsze wersje nie będą mogły ich używać, ponieważ nie mają tych pól w swojej strukturze obiektu.

Mniej oczywiste - gdy deserializujesz obiekt, pola, których nie ma w łańcuchu, będą zachowywane jako NULL. Jeśli usunąłeś pole z obiektu, starsze wersje zachowają to pole jako allways-NULL, co może prowadzić do niewłaściwego zachowania, jeśli starsze wersje polegają na danych w tym polu (w każdym razie stworzyłeś je dla czegoś, a nie tylko dla Zabawy :-) )

Najmniej oczywiste - Czasami zmieniasz pomysł, który wkładasz w znaczenie jakiejś dziedziny. Na przykład, gdy masz 12 lat, masz na myśli "rower" pod "rower", ale gdy masz 18 lat masz na myśli "motocykl" - jeśli Twoi znajomi zaproszą Cię do "jazdy rowerem po mieście" i będziesz jedynym, który przyjechał na rowerze, zrozumiesz, jak ważne jest, aby zachować to samo znaczenie między polami: -) {]}

 1
Author: Stanislav Orlov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-15 16:55:03

Po pierwsze, aby odpowiedzieć na twoje pytanie, Kiedy nie deklarujemy SerialVersionUID w naszej klasie, Java runtime generuje go dla nas, ale ten proces jest wrażliwy na wiele metadanych klasy, w tym liczbę pól, Typ pól, modyfikator dostępu pól, interfejs zaimplementowany przez klasę itp. Dlatego zaleca się, aby zadeklarować to sami i Eclipse ostrzega Cię przed tym samym.

Serializacja: Często pracujemy z ważnymi obiektami, których stan (dane w zmiennych obiektu) jest tak ważne, że nie możemy ryzykować utraty go z powodu awarii zasilania / systemu (lub) sieci w przypadku wysłania stanu obiektu do innej maszyny. Rozwiązanie tego problemu nosi nazwę "Persistence", co po prostu oznacza utrzymywanie (przechowywanie/zapisywanie) danych. Serializacja jest jednym z wielu innych sposobów osiągnięcia trwałości (poprzez zapisanie danych na dysku / pamięci). Podczas zapisywania stanu obiektu, ważne jest, aby utworzyć tożsamość dla obiektu, aby móc poprawnie odczytać go z powrotem (de-serializacja). Ta unikalna identyfikacja to ID is SerialVersionUID.

 1
Author: Shanks D Shiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-29 05:06:22

Co To jest SerialVersionUID? Odpowiedź: - powiedzmy, że są dwie osoby, jedna z centrali i druga z ODC, obie będą wykonywać serializację i deserializację odpowiednio. W tym przypadku, aby potwierdzić, że odbiorca, który jest w ODC, jest uwierzytelnioną osobą, JVM tworzy unikalny identyfikator, który jest znany jako SerialVersionUID.

Oto ładne Wyjaśnienie oparte na scenariuszu,

Dlaczego SerialVersionUID?

Serializacja: w czasie serializacji, przy każdym obiekcie po stronie nadawcy JVM zapisze unikalny identyfikator. JVM jest odpowiedzialny za wygenerowanie tego unikalnego identyfikatora na podstawie odpowiedniego .plik klasy, który jest obecny w systemie nadawcy.

Deserialization: w czasie deserializacji, po stronie odbiornika JVM porównuje unikalny identyfikator skojarzony z obiektem z lokalną klasą Unique ID, tzn. JVM utworzy również unikalny identyfikator na podstawie odpowiedniego .plik klasy, który jest obecny w systemie odbiorczym. Jeśli oba unikalne ID dopasowane wtedy zostanie wykonana tylko deserializacja. W przeciwnym razie otrzymamy wyjątek Runtime mówiący InvalidClassException. Ten unikalny IDENTYFIKATOR to nic innego jak SerialVersionUID

 0
Author: forkdbloke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 16:06:05