我正在使用Kryonet和Slick2d制作一个java游戏。
当作为Java应用程序运行时它工作正常,但是当作为applet运行时,我收到以下错误:
00:00 INFO: [kryonet] Server opened.
00:04 DEBUG: [kryonet] Port 9991/TCP connected to: /(ip):55801
00:04 DEBUG: [kryo] Write: RegisterTCP
00:04 INFO: [kryonet] Connection 1 connected: /(ip)
00:04 INFO: [SERVER] Someone has connected.
00:04 ERROR: [kryonet] Error reading TCP from connection: Connection 1
com.esotericsoftware.kryonet.KryoNetException: Error during deserialization.
at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:141)
at com.esotericsoftware.kryonet.Server.update(Server.java:192)
at com.esotericsoftware.kryonet.Server.run(Server.java:350)
at java.lang.Thread.run(Unknown Source)
Caused by: com.esotericsoftware.kryo.KryoException: Buffer underflow.
at com.esotericsoftware.kryo.io.Input.require(Input.java:162)
at com.esotericsoftware.kryo.io.Input.readLong(Input.java:621)
at com.esotericsoftware.kryo.io.Input.readDouble(Input.java:745)
at com.esotericsoftware.kryo.serializers.DefaultSerializers$DoubleSerializer.read(DefaultSerializers.java:141)
at com.esotericsoftware.kryo.serializers.DefaultSerializers$DoubleSerializer.read(DefaultSerializers.java:131)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:735)
at com.esotericsoftware.kryonet.KryoSerialization.read(KryoSerialization.java:57)
at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:139)
... 3 more
00:04 INFO: [SERVER] Someone has disconnected.
00:04 INFO: [kryonet] Connection 1 disconnected.
服务器在本地作为可运行的jar运行,客户端applet在本地的HTML文件中运行,运行xampp作为Web服务器。
我尝试过不同的序列化程序,缓冲区大小和发送单个字符串/布尔值等,它似乎并不喜欢任何东西。 客户端连接到服务器完全正常,但是当发送任何数据包时,无论发送什么数据包,我都会收到上述错误。
任何帮助/建议都会非常感激 - 我已经被遗忘了一段时间了! 感谢
答案 0 :(得分:0)
我在gradle构建中遇到类似的问题。可能只需要为applet JVM增加内存(堆或PermSize)
答案 1 :(得分:0)
我相信我有同样的问题,或至少是类似的问题。我正在使用Kryonet服务器和客户端。客户端是一个小程序,当我通过Eclipse的Applet Viewer运行它时它工作正常。当我通过Web服务器运行时,我得到类似的错误。客户端和服务器连接,服务器接收客户端的数据包,但客户端在尝试任何反序列化的任何地方都会出错。我发现applet的权限是罪魁祸首。如果将Applet Viewer(如果使用的是Eclipse)的权限更改为与Web页面相同,则会出现相同的错误。优点是您可以调试问题。
要更改Eclipse的权限: 转到项目文件夹\ bin \并打开“java.policy.applet”。你应该在里面:
grant {
permission java.security.AllPermission;
};
将其更改为:
grant {
permission java.io.FilePermission "<<ALL FILES>>", "read, write, execute, delete";
permission java.net.SocketPermission "*", "accept, connect, listen, resolve";
permission java.util.PropertyPermission "*", "read, write";
permission java.lang.RuntimePermission "*";
permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
};
通过此更改,我对Applet Viewer具有与嵌入式applet相同的行为。这不是一个完整的解决方案,但可以帮助找到问题的原因。
更新: 我发现我的问题是什么问题。问题出在FieldSerializer和其他使用它的序列化程序中。当一个类被注册时,FieldSerializer会遍历它的字段并将它们全部设置为可访问。 applet不允许此操作。结果是错误的注册和序列化/反序列化。我找到了2个解决方法:
1)使用其他序列化程序。默认值为FieldSerializer,可以使用
进行更改public void setDefaultSerializer (Class<? extends Serializer> serializer)
另一种选择是在注册每个类时设置序列化程序。不要使用基于FieldSerializer的序列化程序。
2)尝试修复FieldSerializer。我所做的并不完全正确,但它适用于我的情况。如果可访问性的设置导致异常,我们将使FieldSerializer继续注册。我们需要做的另一件事是将我们注册的类的所有字段设置为public。要更改FieldSerializer,您需要Kryo源。转到FieldSerializer.java,找到rebuildCachedFields()。您将在那里找到以下代码:
if (!field.isAccessible()) {
if (!setFieldsAsAccessible) continue;
try {
field.setAccessible(true);
} catch (AccessControlException ex) {
continue;
}
}
您需要将其更改为:
if (!field.isAccessible()) {
if (setFieldsAsAccessible)
try {
field.setAccessible(true);
} catch (AccessControlException ex) {
}
}
需要更改的另一件事是所有已注册的类只有公共字段。