Java Kryonet Грешка при изпращане на обект

Използвам Kryonet за TCP изпращане на обекти, особено един, наречен TransferMessage:

public static class TransferMessage{String text; String username; Color color = Color.black;}

Сега знам, че трябва да извикам kryo.register(TransferMessage.class), но когато се опитам да се свържа със сървъра с всички регистрирани класове, получавам грешка:

    Exception in thread "Server" com.esotericsoftware.kryo.KryoException: java.lang.IllegalArgumentException: Class is not registered: java.awt.Color
Note: To register this class use: kryo.register(java.awt.Color.class);
Serialization trace:
color (com.andrewlalisofficial.MessageTypes$TransferMessage)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:585)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
    at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:571)
    at com.esotericsoftware.kryonet.KryoSerialization.write(KryoSerialization.java:50)
    at com.esotericsoftware.kryonet.TcpConnection.send(TcpConnection.java:192)
    at com.esotericsoftware.kryonet.Connection.sendTCP(Connection.java:59)
    at com.esotericsoftware.kryonet.Server.sendToAllTCP(Server.java:435)
    at com.andrewlalisofficial.ChatServer.sendMessage(ChatServer.java:204)
    at com.andrewlalisofficial.ChatServer.checkCommand(ChatServer.java:124)
    at com.andrewlalisofficial.ChatServer$1.received(ChatServer.java:72)
    at com.esotericsoftware.kryonet.Server$1.received(Server.java:61)
    at com.esotericsoftware.kryonet.Connection.notifyReceived(Connection.java:246)
    at com.esotericsoftware.kryonet.Server.update(Server.java:208)
    at com.esotericsoftware.kryonet.Server.run(Server.java:356)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: Class is not registered: java.awt.Color

Не разбирам, защото въпреки че регистрираният ми клас използва класа Color, никога преди не ми се е налагало да регистрирам String обекти, така че не виждам каква е разликата тук и как да поправя тази грешка? Благодаря ви предварително за помощта.

РЕДАКТИРАНЕ:

Ето минимален възпроизводим код, показващ грешка при сериализиране на Color:

// this works actually fine
public static void main(String[] args) {
    Kryo kryo = new Kryo();
    kryo.register(Color.class, new JavaSerializer());

    Color color = new Color(15006);

    Output output = new Output(new byte[1024]);
    kryo.writeObject(output, color);

    Input input = new Input(output.getBuffer());
    Color color2 = kryo.readObject(input, Color.class);

    if (!color.equals(color2)) throw new AssertionError();
}

person Andrew Lalis    schedule 01.10.2015    source източник
comment
Това не е идеално направено. Бих разширил KryoRegistrator и бих използвал един за инициализиране на един Kryo екземпляр от всяка страна на TCP връзката. Това би гарантирало, че двете страни са регистрирали едни и същи класове с едни и същи сериализатори   -  person Dici    schedule 01.10.2015
comment
Всъщност работи с JavaSerializer, когато е направено правилно. Не знам какъв точно ти е проблемът. Погледнах кода на Color и изглежда, че много данни ще бъдат сериализирани, докато могат просто да бъдат реконструирани след десериализация. Мисля, че можете спокойно да се придържате към персонализирания сериализатор, той е малко по-ефективен, освен ако реконструирането на частните атрибути, които не сериализираме, е по-скъпо от цената на мрежата за тяхното сериализиране   -  person Dici    schedule 01.10.2015


Отговори (1)


String трябва да бъде регистриран по подразбиране. Самият аз съм малко изненадан от тази грешка, защото винаги съм успявал да сериализирам класове, които не съм регистрирал, просто защото Kryo притежава сериализатори по подразбиране за тривиално сериализируеми класове. Както и да е, тъй като java.awt.Color внедрява java.io.Serializable, аз просто бих го направил

kryoRegistrator.register(Color.class, new JavaSerializer());

Можете също така да напишете свой собствен сериализатор (използвайки Kryo), ако искате, но не съм сигурен, че си заслужава (това е просто цяло число за сериализиране, няма начин стандартната библиотека да го прави неефективно). Ако все пак го искате, ето го:

public class ColorSerializer extends Serializer<Color> {
    @Override
    public Color read(Kryo kryo, Input input, Class<Color> clazz) {
        return new Color(input.readInt());
    }

    @Override
    public void write(Kryo kryo, Output output, Color color) {
        output.write(color.getRGB());
    }
}
person Dici    schedule 01.10.2015
comment
Направих това, но сега получавам тази грешка: Изключение в нишката Клиент com.esotericsoftware.kryonet.KryoNetException: Грешка по време на десериализация. на com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:141) на com.esotericsoftware.kryonet.Client.update(Client.java:247) на com.esotericsoftware.kryonet.Client.run(Client.java:333 ) в java.lang.Thread.run(Thread.java:745) Причинено от: com.esotericsoftware.kryo.KryoException: Грешка по време на Java десериализация. - person Andrew Lalis; 01.10.2015
comment
Добре, това е озадачаващо. Имате ли възпроизводим код за това? Можете ли да напишете минимален код, просто включващ вашите класове данни и Kryo? Можете ли също да опитате да напишете свой собствен Kryo сериализатор за Color? - person Dici; 01.10.2015
comment
Не знам как да създам свой собствен сериализатор и гледайки документите, не виждам какво бих заменил. Грешката възниква, когато клиентът получи обект TransferMessage, който съдържа сериализиран обект Color. - person Andrew Lalis; 01.10.2015
comment
Това е изключително лесно. Ще ви го покажа, но моля, опитайте да ми създадете малък пример, възпроизвеждащ грешката. Искам да го разбера. - person Dici; 01.10.2015
comment
Просто въведете кода, който имам. За да го направя малък, но възпроизводим, ще е необходимо основно да напиша три чисто нови програми, така че се надявам, че това, което имам, е достатъчно. - person Andrew Lalis; 01.10.2015