Java getting serializer error with kryonet and slick2d?

I am trying to execute this server code.

package server;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import org.apache.logging.log4j.message.Message;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.minlog.Log;

import Client.PlayerChar;
import NetworkClasses.LoginRequest;
import NetworkClasses.LoginResponse;

public class MainServer {

    private int tcpPort;
    private int udpPort;
    public static Server server;
    private Kryo kryo;

    static JFrame jFrame;
    static JTextArea jTextArea;
    static MainServerListener listener = new MainServerListener();

    public MainServer(int tcpPort, int udpPort) {
        this.tcpPort = tcpPort;
        this.udpPort = udpPort;
        server = new Server();

        kryo = server.getKryo();
        registerKryoClasses();
    }

    public void startServer() {
        Log.info("Starting Server");
        jTextArea.append("Starting Server...");
        jTextArea.append("\n");
        server.start();
        try {
            server.bind(tcpPort, udpPort);
            server.addListener(listener);
            jTextArea.append("Server online! \n");
            jTextArea.append("----------------------------");
            jTextArea.append("\n");
            update();
        } catch (IOException e) {
            Log.info("Port already used");
            jTextArea.append("Port already in use");
            jTextArea.append("\n");
            e.printStackTrace();
        }
    }

    // Try changing this to non staic and see where this effects our game
    public static void stopServer() {
        Log.info("Server stopped");
        jTextArea.append("Server stopped.");
        jTextArea.append("\n");
        server.stop();
    }

    public void update() {
        while (true) {

        }
    }

    private void registerKryoClasses() {
        kryo.register(LoginRequest.class);
        kryo.register(LoginResponse.class);
        kryo.register(Message.class);
        kryo.register(PlayerChar.class);
        kryo.register(org.newdawn.slick.geom.Rectangle.class);
        kryo.register(float[].class);
        kryo.register(NetworkClasses.PacketUpdateX.class);
        kryo.register(NetworkClasses.PacketUpdateY.class);
        kryo.register(NetworkClasses.PacketAddPlayer.class);
        kryo.register(NetworkClasses.PacketRemovePlayer.class);

    }

    public static void createServerInterface() {
        jFrame = new JFrame("GameServerInterface");
        jTextArea = new JTextArea();
        jTextArea.append("\n");
        jTextArea.setLineWrap(true);
        jTextArea.setEditable(false);

        jFrame.add(jTextArea);
        jFrame.setSize(400, 600);
        jFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                int i = JOptionPane.showConfirmDialog(null, "You want to shut down the server?");
                if(i == 0) {
                    stopServer();
                    System.exit(0); // successful exit
                }
            }
        });

        JScrollPane scrollPane = new JScrollPane(jTextArea);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        jFrame.add(scrollPane);
    }

    public static void main(String args[]) {
        Log.set(Log.LEVEL_INFO);

        MainServer main = new MainServer(55555, 55556);
        createServerInterface();
        main.startServer();
    }

} // end total class

Full source code is at https://github.com/schepan1/ms/tree/master/src/main/java. However when I try to run this server, I keep getting this error/exception and there are no solutions online at all. How can I solve this?

Exception in thread "main" java.lang.IllegalArgumentException: Unable to create serializer "com.esotericsoftware.kryo.serializers.FieldSerializer" for class: com.esotericsoftware.kryonet.FrameworkMessage$RegisterTCP
    at com.esotericsoftware.kryo.Kryo.newSerializer(Kryo.java:337)
    at com.esotericsoftware.kryo.Kryo.newDefaultSerializer(Kryo.java:316)
    at com.esotericsoftware.kryo.Kryo.getDefaultSerializer(Kryo.java:309)
    at com.esotericsoftware.kryo.Kryo.register(Kryo.java:353)
    at com.esotericsoftware.kryonet.KryoSerialization.<init>(KryoSerialization.java:33)
    at com.esotericsoftware.kryonet.KryoSerialization.<init>(KryoSerialization.java:25)
    at com.esotericsoftware.kryonet.Server.<init>(Server.java:91)
    at com.esotericsoftware.kryonet.Server.<init>(Server.java:73)
    at server.MainServer.<init>(MainServer.java:36)
    at server.MainServer.main(MainServer.java:118)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.esotericsoftware.kryo.Kryo.newSerializer(Kryo.java:324)
    ... 9 more
Caused by: java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected
    at com.esotericsoftware.reflectasm.FieldAccess.insertConstructor(FieldAccess.java:144)
    at com.esotericsoftware.reflectasm.FieldAccess.get(FieldAccess.java:109)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.rebuildCachedFields(FieldSerializer.java:104)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.<init>(FieldSerializer.java:50)
    ... 14 more

Hi.


Caused by: java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected

I guess it’s happened due the fact that your code tries to create instance of interface MethodVisitor…

I think you have to create your own serializer for the class that’s on the start of the last stack trace.

EDIT: Btw, as I see you use Kryonet 2.22-rc1, but AFAIK Kryonet 4 is released.

Sorry, I’ve mistaken Kryonet for Kryo. :slight_smile:

In your case, the IncompatibleClassChangeError likely happens because the caller - in this case Kryo’s reflectasm.FieldAccess class - expects the callee - in this case asm’s MethodVisitor - to be something which it is not.
ASM changed the “kind” of all visitor classes between version 4 and 5 from interfaces to classes.
Therefore, everyone who wants to call a method on a class must use a different JVM bytecode opcode (INVOKEVIRTUAL) than when calling a method on an interface (INVOKEINTERFACE). So, in this case, Kryo expects the asm.MethodVisitor to be a class (because it calls INVOKEVIRTUAL) whereas in reality at runtime it is an interface, so the JVM expects and enforces the caller to use INVOKEINTERFACE instead. Which kryo did not do. And therefore: boom!

Another possible cause is that Kryo’s reflectasm is declaring a class which extends (as in extend from a class) ASM’s MethodVisitor, which it thought would be a class, but in reality it is an interface.

Yet another possible cause is what Stranger said, that Kryo’s reflectasm code is trying to use the NEW keyword/opcode to instantiate the MethodVisitor type which it thinks is a class, but in reality it is an interface.

The root cause of this is that you are using an incompatible ASM library version (likely 5, which is using classes for the visitor classes, instead of interfaces) for your Kryo version.
Steps in order to fix it: Use compatible Kryo and ASM versions.