GSON 在 运行 toJSON 时导致 StackOverFlow 错误

GSON causing StackOverFlow Error when running toJSON

在我开始这个问题之前,我知道有很多类似的问题但是我无法控制我变成的对象 JSON 因此我不能简单地排除引用同一对象的字段。

我发现解释我的应用程序的结构有助于人们更好地理解我的问题,所以我开始了!

我有 2 个应用程序,一个 Logic 应用程序(所有繁重的操作都在其中进行)和一个 Instrumented 应用程序(一个注入到旧游戏中并且必须保持轻量的应用程序)。

这 2 个应用程序通过 RMI(远程方法调用)进行通信。

Instrumented 应用程序使用反射 API 将从旧游戏中获取的对象发送到逻辑应用程序(通过 RMI,因为这是 2 通信的方式)。

大多数对象是不可序列化的(不要实现可序列化,并且不能序列化,除非使用 BCL 库,我不想这样做,因为强制序列化对象是不好的做法,因为它们可能导致问题(安全)序列化)。

如上段所述,由于它们是不可序列化的,我不能只将它们转换为字节数组并发送,所以我经历并使用了不需要对象实现可序列化的 GSON .

当我第一次尝试序列化对象时,除了在尝试序列化它们时打印出堆栈溢出错误的几个对象外,它是有效的 (toJSON)。

我认为错误发生的原因: 该对象有一个超类.. 该对象包含自身的引用(字段)

我无法显示对象本身,因为它在游戏中并且被混淆了,但我可以向它显示我的包装器,它显示了字段及其类型。

对象本身(当对其执行 toJSON 时导致堆栈溢出错误的对象):

public class NPC extends Model {

    //The Class itself contains 1 field which is "Composite"

    public NPC(Object object) {
        super(object);
    }

    public NPCComposite getComposite() {
        return new NPCComposite(getFieldValue("Npc.composite", object));
    }
}

上面的对象只包含 1 个字段,它是“复合的”,这里是 NPCComposite 的包装器:

public class NPCComposite extends Wrapper {

    //Contains 3 Fields: String[], String, int (Nothing out of the ordinary)
    
    public NPCComposite(Object object) {
        super(object);
    }

    public String[] getActions() {
        return (String[]) getFieldValue("NpcComposite.actions", object);
    }

    public int getID() {
        return (int) getFieldValue("NpcComposite.id", object);
    }

    public String getName() {
        return (String) getFieldValue("NpcComposite.name", object);
    }
}

如果你注意到了,对象本身 (NPC) 有一个超类,这是超类的包装器: 我在具有不明显 return 类型的字段吸气剂旁边添加了评论。

public class Model extends Render {

    public Model(Object object) {
        super(object);
    }

    public int getFineX() {
        return (int) getFieldValue("Model.localX", object);
    }

    public int getFineY() {
        return (int) getFieldValue("localY", object);
    }

    public int getAnimation() {
        return (int) getFieldValue("animation", object);
    }

    public int getAnimationDelay() {
        return (int) getFieldValue("animationDelay", object);
    }

    public int getCombatTime() {
        return (int) getFieldValue("combatTime", object);
    }

    public int getStandAnimation() {
        return (int) getFieldValue("standAnimation", object);
    }

    public int getFrameOne() {
        return (int) getFieldValue("frameOne", object);
    }

    public int getFrameTwo() {
        return (int) getFieldValue("Model.frameTwo", object);
    }

    public Object getHealthBars() { //Returns a Health Bar Object
        return getFieldValue("Model.healthBars", object);
    }

    public Object getHitCycles() { //Returns an Integer 1D Array
        return getFieldValue("Model.hitCycles", object);
    }

    public Object getHitDamages() { //Returns an Integer 1D Array
        return getFieldValue("Model.hitDamages", object);
    }

    public Object getHitTypes() { //Returns an Integer 1D Array
        return getFieldValue("Model.hitTypes", object);
    }

    public int getInteracting() {
        return (int) getFieldValue("Model.interacting", object);
    }

    public Object getMessage() { //Returns a String
        return getFieldValue("Model.message", object);
    }

    public int getOrientation() {
        return (int) getFieldValue("Model.orientation", object);
    }

    public int getQueueSize() {
        return (int) getFieldValue("Model.queueSize", object);
    }

    public Object getQueueTraversed() { //Returns a byte 1D array
        return getFieldValue("Model.queueTraversed", object);
    }

    public Object getQueueX() { //Returns a 1D int array
        return getFieldValue("Model.queueX", object);
    }

    public Object getQueueY() { //Returns a 1D int array
        return getFieldValue("Model.queueY", object);
    }

    public int getRuntimeAnimation() {
        return (int) getFieldValue("Model.runtimeAnimation", object);
    }

}

主要方法:

    Gson g = new Gson();
    String res = g.toJson(NPCObject);

错误:

java.rmi.ServerError: Error occurred in server thread; nested exception is: 
    java.lang.WhosebugError
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at sun.rmi.transport.Transport.run(Unknown Source)
    at sun.rmi.transport.Transport.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run[=15=](Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:303)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:279)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:163)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:235)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:180)
    at com.sun.proxy.$Proxy0.getGSONValue(Unknown Source)
    at main.Instance.test(Instance.java:29)
Caused by: java.lang.WhosebugError
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuffer.append(Unknown Source)
    at java.io.StringWriter.write(Unknown Source)
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:590)
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401)
    at com.google.gson.stream.JsonWriter.value(JsonWriter.java:526)
    at com.google.gson.internal.bind.TypeAdapters.write(TypeAdapters.java:311)
    at com.google.gson.internal.bind.TypeAdapters.write(TypeAdapters.java:296)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1027)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)

我的问题是:有什么办法可以解决这个错误吗?或者是否有任何其他 JSON 库可以序列化此类对象?任何答案表示赞赏!

谢谢!

我认为除了使用 BCEL 库并将循环字段更改为瞬态或使 class 可序列化及其内容之外没有其他解决方法..

我已经通过使用 XStream 并将对象的 class 路径添加到其中成功解决了这个问题。