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 路径添加到其中成功解决了这个问题。
在我开始这个问题之前,我知道有很多类似的问题但是我无法控制我变成的对象 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 路径添加到其中成功解决了这个问题。