Подтвердить что ты не робот

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;
}
4b9b3361

Ответ 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