Java.io.InvalidClassException: локальный класс несовместим:
Я создал клиент и сервер, а затем добавил класс на стороне клиента для целей сериализации, а затем просто просто перешел в папку клиента на моем жестком диске и скопировал его и вставил в соответствующее местоположение сервера, соответственно classname.class
и classname.java
,
Это хорошо работало на моем ноутбуке, но когда я хотел продолжить свою работу в другой системе, когда я открывал папки проектов и после того, как клиент пытается подключиться к серверу, появляется следующая ошибка:
Exception in thread "main" java.io.InvalidClassException: projectname.clasname; local class incompatible: stream classdesc serialVersionUID = -6009442170907349114, local class serialVersionUID = 6529685098267757690
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
Что здесь происходит? Это потому, что я запустил программу с более старой версией IDE?
РЕДАКТИРОВАТЬ
import java.io.Serializable;
import java.net.URL;
public class KeyAdr implements Serializable {
private static final long serialVersionUID = 6529685098267757690L;
public URL adr;
public String key;
}
Ответы
Ответ 1
Если класс не определяет явным образом private static final long serialVersionUID
в коде, он будет автогенерирован, и нет гарантии, что разные машины будут генерировать один и тот же идентификатор; похоже, что это именно то, что произошло.
Также, если классы каким-либо образом отличаются (с использованием разных версий класса), автогенерируемый serialVersionUID
также будет отличаться.
В интерфейсе Serializable
docs:
Если сериализуемый класс явно не объявляет serialVersionUID
, то среда выполнения сериализации будет вычислять значение по умолчанию serialVersionUID
для этого класса на основе различных аспектов класса, как описано в спецификации Java Serialization Java (TM), Тем не менее, настоятельно рекомендуется, чтобы все сериализуемые классы явно объявляли значения serialVersionUID
, так как вычисление по умолчанию serialVersionUID
очень чувствительно к деталям класса, которое может меняться в зависимости от реализаций компилятора и, таким образом, может привести к неожиданному InvalidClassExceptions
во время десериализации. Поэтому, чтобы гарантировать согласованное значение serialVersionUID
в разных реализациях java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID
. Также настоятельно рекомендуется, чтобы явные объявления serialVersionUID
использовали модификатор private
, где это возможно, поскольку такие объявления применимы только к полям, объявляющим сразу же объявление - serialVersionUID
не полезны в качестве унаследованных членов. Классы массивов не могут объявить явный serialVersionUID
, поэтому они всегда имеют вычисленное значение по умолчанию, но требование для сопоставления значений serialVersionUID
отменяется для классов массивов.
Вы должны определить serialVersionUID
в определении класса, например:
class MyClass implements Serializable {
private static final long serialVersionUID = 6529685098267757690L;
...
Ответ 2
Одна вещь, которая могла бы случиться:
- 1: вы создаете свои сериализованные данные с заданной библиотекой A (версия X)
- 2: вы затем пытаетесь прочитать эти данные с той же библиотекой A (но версия Y)
Следовательно, во время компиляции для версии X JVM сгенерирует первый серийный идентификатор (для версии X) и сделает то же самое с другой версией Y (другой серийный идентификатор).
Когда ваша программа пытается десериализовать данные, она не может этого сделать, потому что два класса не имеют одинаковый серийный идентификатор, а ваша программа не гарантирует, что два сериализованных объекта соответствуют одному и тому же формату класса.
Предполагая, что вы поменяли конструктор за это время, это должно иметь для вас смысл.
Ответ 3
Я считаю, что это происходит потому, что вы используете разные версии одного и того же класса на клиенте и сервере.
Это могут быть разные поля данных или методы.
Ответ 4
Сериализация в java не означает долговременного сохранения или транспортного формата - для этого она слишком хрупка. С малейшей разницей в классе байт-кода и JVM ваши данные больше не читаются. Используйте привязку данных XML или JSON для вашей задачи (XStream является быстрым и простым в использовании, и есть тонна альтернатив)
Ответ 5
Сообщение об исключении четко говорит о том, что версии классов, которые также будут включать метаданные класса, со временем изменились. Другими словами, структура класса во время сериализации не является одинаковой во время де-сериализации. Это то, что, скорее всего, "происходит".
Ответ 6
Если вы используете oc4j для развертывания уха. Убедитесь, что в проекте указан правильный путь для deploy.home = oc4j необходимо перезагрузить новый созданный класс в ухо, чтобы класс сервера и класс клиента имели одинаковый serialVersionUID