2012-04-30 2 views
19

Создал клиент и сервер, а затем добавил класс на стороне клиента для сериализации, а затем просто перешел в папку клиента на моем жестком диске и скопировал его в серверное соответствующее местоположение, как classname.class, так и classname.java соответственно.java.io.InvalidClassException: локальный класс несовместим:

Он работал хорошо в моем собственном ноутбуке, но когда я хотел бы продолжить свою работу по другой системе, когда я открыл папку проектов и после того, как клиент пытается соединиться с сервером, появляется следующее сообщение об ошибке:

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?

EDIT

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; 


} 

ответ

27

Если класс не явно определить в коде на private static final long serialVersionUID будет генерироваться автоматически, и нет никакой гарантии, что разные машины будут генерировать тот же идентификатор; похоже, что это именно то, что произошло. Также, если классы отличаются друг от друга (с использованием разных версий класса), автогенерированные serialVersionUID s также будут отличаться.

Из интерфейса Serializabledocs:

Если сериализации класс не явно объявить serialVersionUID, то сериализации во время выполнения будет вычислять значение по умолчанию serialVersionUID для этого класса, основываясь на различных аспектах класса, как описано в Спецификации Сериализации объектов Java (TM). Тем не менее, настоятельно рекомендовал, что все сериализуемые классы явно объявляют значения serialVersionUID, так как вычисление по умолчанию serialVersionUID очень чувствительно к деталям класса, которые могут различаться в зависимости от реализаций компилятора и, таким образом, могут привести к неожиданному InvalidClassExceptions во время десериализации. Поэтому, чтобы гарантировать согласованное значение serialVersionUID в разных реализациях java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID. Также настоятельно рекомендуется, чтобы явные объявления serialVersionUID использовали модификатор private, если это возможно, поскольку такие объявления применяются только к классу, объявляющему сразу: поля serialVersionUID не полезны в качестве унаследованных. Классы массивов не могут объявить явный serialVersionUID, поэтому они всегда имеют рассчитанное по умолчанию значение, но требование для сопоставления значений serialVersionUID отменяется для классов массивов.

Вы должны определить в определении класса в serialVersionUID, например .:

class MyClass implements Serializable { 
    private static final long serialVersionUID = 6529685098267757690L; 
    ... 
+0

как отрегулировать serialVersionUID в определении? – lonesome

+0

по-прежнему такая же ошибка – lonesome

+0

Это странно. Я бы дважды проверить, что обе стороны используют новейшую версию класса. – trutheality

0

Я считаю, что это происходит потому, что вы используете различные версии одного и того же класса на клиенте и сервере. Это могут быть разные поля или методы данных.

0

Сериализация в java не означает, что она является долговременной настойчивостью или транспортным форматом - она ​​слишком хрупка для этого. С малейшей разницей в классе байт-кода и JVM ваши данные больше не читаются.Используйте привязку данных XML или JSON для своей задачи (XStream - это быстрый и простой в использовании, и есть тонна альтернатив)

+2

Я могу согласиться на степень стойкости, но нет ничего плохого в использовании Java Serialization в качестве транспортного формата. Это слишком хрупко, если вы не знаете понятия сериализации Java, например 'serialVersionUID'. –

+0

Это хрупкое даже тогда. –

+0

Это не так. Возможно, мы просто видим мир Java-сериализации с разными цветными очками. Плюс это почти единственный вариант при использовании RMI. Кроме того, я вижу, что вы кое-что высказали по поводу того, что «менеджер проекта скинирует что-то», который был отредактирован позже ... –

0

Сообщение об исключении четко говорит о том, что версии классов, которые также будут включать метаданные класса , со временем изменился. Другими словами, структура класса во время сериализации не является одинаковой во время де-сериализации. Это, скорее всего, «происходит».

Смежные вопросы