1

Slick2d で Kryonet を使用して Java ゲームを作成しています。

Java アプリケーションとして実行すると問題なく動作しますが、アプレットとして実行すると次のエラーが発生します。

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 としてローカルで実行され、クライアント アプレットはローカルでも HTML ファイルで実行され、xampp を実行して Web サーバーとして機能します。

さまざまなシリアライザー、バッファーサイズ、単一の文字列/ブール値などを送信してみましたが、何も気に入らないようです。クライアントはサーバーに完全に接続しますが、パケットを送信すると、どのパケットが送信されても​​上記のエラーが発生します。

ヘルプ/アドバイスをいただければ幸いです-私はしばらくこれに悩まされていました! ありがとう

4

2 に答える 2

0

私は同じ問題、または少なくとも同様の問題を抱えていると思います。サーバーとクライアントに Kryonet を使用しています。クライアントはアプレットであり、Eclipse の Applet Viewer を介して実行すると正常に動作します。Web サーバーを介して実行すると、同様のエラーが発生します。クライアントとサーバーが接続し、サーバーがクライアントのパケットを受信しますが、クライアントがデシリアライズを試みるたびにエラーが発生します。アプレットのアクセス許可が原因であることがわかりました。アプレット ビューアー (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";  
};

この変更により、アプレット ビューアーの動作は埋め込みアプレットの場合と同じになりました。これは完全な解決策ではありませんが、問題の原因を見つけるのに役立ちます。

更新: 私の場合、何が問題なのかがわかりました。問題は、FieldSerializer とそれを使用する他のシリアライザーにあります。クラスが登録されると、FieldSerializer はそのフィールドを調べて、それらすべてにアクセスできるように設定します。この操作はアプレットには許可されていません。その結果、間違った登録とシリアライゼーション/デシリアライゼーションが発生します。私は2つの回避策を見つけました:

1) 別のシリアライザーの使用。デフォルトのものは FieldSerializer で、次を使用して変更できます

public void setDefaultSerializer (Class<? extends Serializer> serializer)

別のオプションは、各クラスを登録するときにシリアライザーを設定することです。FieldSerializer に基づくシリアライザーは使用しないでください。

2) FieldSerializer の修正を試みます。私がやっていることは完全に正しいわけではありませんが、私の場合はうまくいきます。アクセシビリティの設定が例外を引き起こしている場合、FieldSerializer に登録を続行させます。もう 1 つ必要なことは、登録するクラスのすべてのフィールドを 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) {
        }
    }

もう 1 つ変更する必要があるのは、登録されているすべてのクラスが public フィールドのみを持つようにすることです。

于 2013-03-08T17:18:46.050 に答える
0

gradleビルドでも同様の問題があります。アプレット JVM のメモリ (ヒープまたは PermSize) を増やすだけでよい場合があります。

于 2013-03-07T12:08:35.673 に答える