简体   繁体   English

GSON 在运行 toJSON 时导致 StackOverFlow 错误

[英]GSON causing StackOverFlow Error when running toJSON

Before I begin with the question, I know there are lots of similar questions to this but I have no control of the objects I turn into JSON therefore I can't simply exclude fields that reference the same object.在我开始提问之前,我知道有很多类似的问题,但我无法控制我变成 JSON 的对象,因此我不能简单地排除引用相同 object 的字段。

I found that explaining the structure of my applications help people understand my question more, so here I go!我发现解释我的应用程序的结构可以帮助人们更多地理解我的问题,所以我开始了!

I have 2 applications, a Logic application (where all the heavy operations take place) and a Instrumented application (an application which is injected into an old game and has to be kept light).我有 2 个应用程序,一个 Logic 应用程序(所有繁重的操作都发生在这里)和一个 Instrumented 应用程序(一个注入旧游戏并且必须保持轻量级的应用程序)。

The 2 applications communicate via RMI (Remote Method Invocation).这两个应用程序通过 RMI(远程方法调用)进行通信。

The Instrumented Application sends Objects that are fetched from the old game using the Reflection API to the Logic Application (via RMI as that's how the 2 communicate).检测应用程序将使用反射 API 从旧游戏中获取的对象发送到逻辑应用程序(通过 RMI,因为这就是 2 通信的方式)。

Most of the objects are Un-serializable (Do not implement Serializable, and can't be serialized except by using BCL libraries which I don't want to do as it's bad practice to force-serialize objects as they may cause problems(security) serialized).大多数对象都是不可序列化的(不要实现可序列化,并且不能序列化,除非使用我不想这样做的 BCL 库,因为强制序列化对象是不好的做法,因为它们可能会导致问题(安全)序列化)。

As mentioned in the above paragraph, due to them being un-serializable I can't just turn them into byte arrays and send so I've went through and used GSON which doesn't require the objects to implement Serializable.如上段所述,由于它们是不可序列化的,我不能只将它们转换为字节 arrays 并发送,所以我已经完成并使用了 GSON,它不需要对象实现可序列化。

When I first tried out serializing the objects, it worked except a couple of objects printed out Stack overflow errors when trying to serialize them (toJSON).当我第一次尝试序列化对象时,它可以工作,除了几个对象在尝试序列化它们时打印出堆栈溢出错误(toJSON)。

Why I think the error occurred: The object has a superclass.. The object contains references of itself (Fields)为什么我认为发生错误:object 有一个超类.. object 包含自身的引用(字段)

I can't show the object itself as it's in a game and its obfuscated, but I can show my wrapper to it which shows the fields and their types.我无法显示 object 本身,因为它在游戏中并且被混淆了,但我可以向它展示我的包装器,它显示了字段及其类型。

The Object Itself (The one causing Stack Overflow errors when toJSON is executed upon it): Object 本身(在其上执行 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));
    }
}

The Object above contains only 1 Field and it's "Composite", here's the wrapper for NPCComposite:上面的 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);
    }
}

If you have noticed, the Object itself (NPC) has a superclass, this is the superclass's wrapper: I have added a comment next to field getters that have unapparent return types.如果您注意到,Object 本身(NPC)有一个超类,这是超类的包装器:我在具有不明显返回类型的字段获取器旁边添加了一条注释。

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);
    }

}

Main method:主要方法:

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

Error:错误:

java.rmi.ServerError: Error occurred in server thread; nested exception is: 
    java.lang.StackOverflowError
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at sun.rmi.transport.Transport$1.run(Unknown Source)
    at sun.rmi.transport.Transport$1.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$0(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.StackOverflowError
    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$11.write(TypeAdapters.java:311)
    at com.google.gson.internal.bind.TypeAdapters$11.write(TypeAdapters.java:296)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.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$1.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)

My question is: Is there anyway to solve this error?我的问题是:有没有办法解决这个错误? or is there any other JSON library that can serialize such objects?还是有任何其他可以序列化此类对象的 JSON 库? any answer is appreciated!任何答案表示赞赏!

Thank you!谢谢!

I have successfully solved this by using XStream and adding the class path of the objects to it.我已经通过使用 XStream 并将对象的 class 路径添加到它成功地解决了这个问题。

I don't think there's a way around it except using BCEL libraries and changing circular fields to transient or making the class Serializable and its contents..我认为除了使用 BCEL 库并将循环字段更改为瞬态或使 class 可序列化及其内容之外,没有其他办法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM