簡體   English   中英

GSON 在運行 toJSON 時導致 StackOverFlow 錯誤

[英]GSON causing StackOverFlow Error when running toJSON

在我開始提問之前,我知道有很多類似的問題,但我無法控制我變成 JSON 的對象,因此我不能簡單地排除引用相同 object 的字段。

我發現解釋我的應用程序的結構可以幫助人們更多地理解我的問題,所以我開始了!

我有 2 個應用程序,一個 Logic 應用程序(所有繁重的操作都發生在這里)和一個 Instrumented 應用程序(一個注入舊游戲並且必須保持輕量級的應用程序)。

這兩個應用程序通過 RMI(遠程方法調用)進行通信。

檢測應用程序將使用反射 API 從舊游戲中獲取的對象發送到邏輯應用程序(通過 RMI,因為這就是 2 通信的方式)。

大多數對象都是不可序列化的(不要實現可序列化,並且不能序列化,除非使用我不想這樣做的 BCL 庫,因為強制序列化對象是不好的做法,因為它們可能會導致問題(安全)序列化)。

如上段所述,由於它們是不可序列化的,我不能只將它們轉換為字節 arrays 並發送,所以我已經完成並使用了 GSON,它不需要對象實現可序列化。

當我第一次嘗試序列化對象時,它可以工作,除了幾個對象在嘗試序列化它們時打印出堆棧溢出錯誤(toJSON)。

為什么我認為發生錯誤:object 有一個超類.. object 包含自身的引用(字段)

我無法顯示 object 本身,因為它在游戲中並且被混淆了,但我可以向它展示我的包裝器,它顯示了字段及其類型。

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

上面的 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);
    }
}

如果您注意到,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);
    }

}

主要方法:

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

錯誤:

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)

我的問題是:有沒有辦法解決這個錯誤? 還是有任何其他可以序列化此類對象的 JSON 庫? 任何答案表示贊賞!

謝謝!

我已經通過使用 XStream 並將對象的 class 路徑添加到它成功地解決了這個問題。

我認為除了使用 BCEL 庫並將循環字段更改為瞬態或使 class 可序列化及其內容之外,沒有其他辦法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM