Search code examples
exceptioncastingkryonet

Kryonet Exception when casting received Object (Bug?)


I have this small piece of code in my class which extends Listener:

@Override
public void received(Connection connection, Object object)
{
    Packet packet = (Packet) object;
    server.addPacket(new ClientPacket(connection.getID(), packet));
}

Whenever I receive an Object, I cast it to an Interface called Packet with a method handle() which every packet implement. I then add it to a ConcurrentLinkedQueue for future processing.

Still, after i spam a few keys which send UDP packets to the server, the following Exception is thrown:

Exception in thread "Server" java.lang.ClassCastException: com.esotericsoftware.kryonet.FrameworkMessage$KeepAlive cannot be cast to com.xkynar.game.net.packet.Packet at com.xkynar.game.net.ServerSocket.received(ServerSocket.java:70) 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(Unknown Source)

The exception occurs in the cast, that is:

Packet packet = (Packet) object;

How can this be possible? What the hell is "FrameworkMessage$KeepAlive" to begin with? Why is it entering my received listener?

Please explain what is wrong, is it my mistake or a bug?


Solution

  • FrameworkMessage is an interface that is used to mark objects as being used internally to the framework. From the documentation:

    public interface FrameworkMessage

    Marker interface to denote that a message is used by the Ninja framework and is generally invisible to the developer. Eg, these messages are only logged at the Log.LEVEL_TRACE level.

    It's safe to assume that your code may not be the only listener to a server. The solution is to check object's identity at run time. This is illustrated in the kryonet readme:

    server.addListener(new Listener() {
        public void received (Connection connection, Object object) {
            if (object instanceof SomeRequest) {
                SomeRequest request = (SomeRequest)object;
    

    In your code, you'd replace SomeRequest with Packet in the above snippet.