【问题标题】:StackOverflowError when serializing an object in Java在 Java 中序列化对象时出现 StackOverflowError
【发布时间】:2010-10-01 03:11:10
【问题描述】:

我正在使用 Swing 用 Ja​​va 编写应用程序。我正在尝试实现在我正在运行的模拟中保存和加载模拟状态的功能。整个模拟被保存为一个对象,与 Swing 断开连接。我正在尝试使用此代码序列化我的 Simulation 类:

public void saveSimulationState(String simulationFile) {
    try {
        Serializable object = this.sm;
        ObjectOutputStream objstream = new ObjectOutputStream(new FileOutputStream(simulationFile));
        objstream.writeObject(object);
        objstream.close();
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
}

但我收到以下错误(非常严重)。

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
        at java.io.ObjectStreamClass.processQueue(ObjectStreamClass.java:2234)
        at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:266)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)

谁能告诉我是什么导致了这个异常?

【问题讨论】:

标签: java swing serialization stack-overflow


【解决方案1】:

来自陈的有趣帖子:

When debugging a stack overflow, you want to focus on the repeating recursive part

在你的情况下:

        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at java.util.ArrayList.writeObject(ArrayList.java:570)
        at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)

如果您通过缺陷跟踪数据库寻找这是否是一个已知问题,则搜索堆栈中的顶级函数不太可能找到任何有趣的东西。这是因为堆栈溢出往往发生在递归中的随机点。每个堆栈溢出看起来都与其他堆栈溢出表面上不同,即使它们是相同的堆栈溢出。

一旦您摆脱了最初的混乱,堆栈跟踪就会稳定下来,形成一个由相同 x 函数一遍又一遍地组成的漂亮重复模式。
确定重复模式的开始并不重要,因为每次碰撞的起点都会不同,就像超出你的歌唱范围的精确音符会随着碰撞而变化一样。

确定重复部分后,从中挑选一个有些不寻常的函数,然后在 your defect database 中搜索它。

For example,默认的ArrayList序列化。

这里您的GrahPanel 指的是Simulation,它指的是Graph,传感器和Edge 的ArrayList 可能很长...

Java 序列化记录写入流的每个对象。如果第二次遇到相同的对象,则只会将对其的引用写入流,而不是对象的第二个副本;所以循环引用不是这里的问题。

但是对于某些类型的结构,序列化容易受到堆栈溢出的影响;例如,没有特殊 writeObject() 方法的长链表将通过递归写入每个链接来序列化。如果您有 100,000 个链接,您将尝试使用 100,000 个堆栈帧,并且很可能会因 StackOverflowError 而失败。

可以为这样的列表类定义 writeObject() 方法,当第一个链接被序列化时,只需遍历列表并迭代地序列化每个链接;这将阻止使用默认的递归机制。

【讨论】:

  • 第一个链接响应 404
【解决方案2】:

您应该考虑重新实现您的 Simulation 类的 writeObject / readObject 方法,以便仅序列化相关数据(而不是默认情况下包含的整个对象结构)或标记瞬态您不被序列化的对象。 如果需要,您也可以使用Externalizable 接口。

顺便说一句,您可能想先阅读此interesting article。

【讨论】:

    【解决方案3】:

    您有一些深度嵌套的 ArrayList。

    我认为它可能只是先进入深度,这意味着它会进入底部传感器,它太深了。

    也许您可以使用从底部传感器开始的传感器创建自定义结构?

    或者您可能必须提供自己的序列化来处理它? http://java.sun.com/developer/technicalArticles/Programming/serialization/

    【讨论】:

      【解决方案4】:

      您应该为要存储的对象创建一个容器类。我不会存储包含所有逻辑的完整这个对象。

      逐个字段存储第一个字段以找到以这种方式存储它的元素。 然后在方法中放置一个断点并查看字段元素。元素是否包含相互链接的链接?

      【讨论】:

        【解决方案5】:

        在您完成所有操作后,如果您只想保存到文件,请改用 XStream。

        【讨论】:

          【解决方案6】:

          这段代码应该作为一个模型,因为它解决了序列化的堆栈溢出问题。它使用内存代替递归。虽然不适合被认为是通用的序列化程序,但它会序列化和反序列化它所测试的类。

          import java.io.*;
          import java.util.*;
          import java.lang.reflect.*;
          import android.util.*;
          
          public class SequentialObjectInputStream extends DataInputStream implements ObjectInput
          {
              interface FieldPutAction
              {
                  void put(Object obj, Field field) throws IllegalAccessException, IOException;
              }
          
              interface ArrayPutAction
              {
                  void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException;
              }
          
              public HashMap<Class, FieldPutAction> Primatives;
              public HashMap<Class, ArrayPutAction> ArrayPrimatives;
          
              public SequentialObjectInputStream(InputStream stream)
              {
                  super(stream);
          
                  Primatives = new HashMap<Class, FieldPutAction>();
          
                  try
                  {
                      Primatives.put(boolean.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  boolean x = readBoolean(); 
                                  field.setBoolean(obj, x);
          
                              }
                          });
          
                      Primatives.put(byte.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  byte x = readByte(); 
                                  field.setByte(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(short.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  short x = readShort(); 
                                  field.setShort(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(int.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  int x = readInt(); 
                                  field.setInt(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(long.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  long x = readLong(); 
                                  field.setLong(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(char.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  char x = readChar(); 
                                  field.setChar(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(float.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  float x = readFloat(); 
                                  field.setFloat(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(double.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  double x = readDouble(); 
                                  field.setDouble(obj, x);
          
                              }
                          });
          
          
                      Primatives.put(String.class,
                          new FieldPutAction()
                          {
                              public void put(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  String x = readUTF(); 
                                  field.set(obj, x);
          
                              }
                          });
                  } catch(Exception e)
                  {
                      Log.e("SOb", Log.getStackTraceString(e));
                  }
          
                  ArrayPrimatives = new HashMap<Class, ArrayPutAction>();
          
                  try
                  {
                      ArrayPrimatives.put(boolean.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  boolean x = readBoolean();
                                  Array.setBoolean(obj, index, x);
                              }
                          });
          
                      ArrayPrimatives.put(byte.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  byte x = readByte(); 
                                  Array.setByte(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(short.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  short x = readShort(); 
                                  Array.setShort(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(int.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  int x = readInt(); 
                                  Array.setInt(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(long.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  long x = readLong(); 
                                  Array.setLong(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(char.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  char x = readChar(); 
                                  Array.setChar(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(float.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  float x = readFloat(); 
                                  Array.setFloat(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(double.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  double x = readDouble(); 
                                  Array.setDouble(obj, index, x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(String.class,
                          new ArrayPutAction()
                          {
                              public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  String x = readUTF(); 
                                  Array.set(obj, index, x);
          
                              }
                          });
                  } catch(Exception e)
                  {
                      Log.e("SOb", Log.getStackTraceString(e));
                  }
              }
          
          
              @Override
              public Object readObject() throws ClassNotFoundException, IOException
              {
                  long Total = readLong();
          
                  Log.i("SOb", "readObject : " + Long.toString(Total) + " objects in graph");
          
                  HashMap<Long, Object> References = new HashMap<Long, Object>();
          
                  long currentId = 1;
          
                  HashMap<Object, HashMap<Field, Long>> refCache =
                      new HashMap<Object, HashMap<Field, Long>>();
                  final HashMap<Object, HashMap<Integer, Long>> arefCache =
                      new HashMap<Object, HashMap<Integer,Long>>();
          
                  for (int I=0; I < Total; I++)
                  {
                      String Name = readUTF();
                      Class C = Class.forName(Name);
          
                      Log.i("SOb", "Object of "+C.getCanonicalName() +" on graph");
          
                      int adim = 0;
          
                      Object O = null;
          
                      if (C.isArray())
                      {
                          Class ComponentType = C.getComponentType();
          
                          int Size = readInt();
          
                          Log.i("SOb", "array of "+ComponentType.getCanonicalName() + ", " + Long.toString(Size) + " elements");          
                          O = Array.newInstance(ComponentType, Size);
          
                          References.put(currentId, O);
                          currentId++;
          
                          ArrayPutAction action = null;
          
                          if (ArrayPrimatives.keySet().contains(ComponentType))
                          {
                              action = ArrayPrimatives.get(ComponentType);
                          } else
                          {
                              arefCache.put(O, new HashMap<Integer, Long>());
          
                              action = new ArrayPutAction()
                              {
                                  public void put(Object O, int Index) throws ArrayIndexOutOfBoundsException , IOException
                                  {
                                      long Ref = readLong();
          
                                      arefCache.get(O).put(Index, Ref);
                                  }
                              };
                          }
          
                          for (int index=0; index< Size; index++)
                          {
                              action.put(O,index);
                          }
          
                      } else
                      {
          
                      try
                      {
          
                          O = 
                              C.getConstructor(new Class[0]).newInstance(new Object[0]);
                      } catch(InstantiationException e)
                      {
                          Log.e("SOb", Log.getStackTraceString(e));
                      } catch(NoSuchMethodException e)
                      {
                          Log.e("SOb", Log.getStackTraceString(e));
                      } catch(IllegalAccessException e)
                      {
                          Log.e("SOb", Log.getStackTraceString(e));
                      } catch(InvocationTargetException e)
                      {
                          Log.e("SOb", Log.getStackTraceString(e));
                      }
          
                      References.put(currentId, O);
                      currentId++;
                      refCache.put(O, new HashMap<Field, Long>());
          
                      for (Field F : C.getFields())
                      {
                          if (F.isAccessible())
                          {
                              Class T = F.getType();
          
                              if (Primatives.containsKey(T))
                              {
                                  try
                                  {
                                      Primatives.get(T).put(O, F);
                                  } catch (IllegalAccessException e)
                                  {
          
                                  }
                              } else
                              {
                                  refCache.get(O).put(F, readLong());
                              }
                          }
                      }
          
                  }
                  }
                  for (long I=0; I < Total; I++)
                  {
          
                      Object O = References.get(I+1);
          
                      Class C = O.getClass();
          
                      //Log.i("SOb", "get reference "+Long.toString(I)+" "+C.getCanonicalName());
          
          
                      if (C.isArray())
                      {
                          HashMap<Integer,Long> aref_table = arefCache.get(O);
          
                          if (ArrayPrimatives.containsKey(C.getComponentType()) == false)
                          {
          
                              int len = Array.getLength(O);
          
                              for (int index=0; index<len; index++)
                              {
                                  long r = aref_table.get(index);
                                  Object ref = r == 0 ? null : References.get(r);
          
                                  Array.set(O, index, ref);   
                              }
                          }
          
                      } else
                      {
          
                      HashMap<Field, Long> ref_table = refCache.get(O);
          
                      for (Field F : C.getFields())
                      {
                          if (F.isAccessible())
                          {
                              Class T = F.getType();
          
                              if (Primatives.containsKey(T) == false)
                              {
                                  try
                                  {
                                      long r = ref_table.get(F);
                                      Object ref = r == 0 ? null : References.get(r);
          
                                      F.set(O, ref);
                                  } catch (IllegalAccessException e)
                                  {
                                      Log.e("SOb", Log.getStackTraceString(e));
                                  }
          
                              }
                          }
                      }
                      }
          
                  }
          
          
                  return References.get((Long) (long) 1);
              }
          
          }
          
          
          import java.io.*;
          import java.util.*;
          import java.lang.reflect.*;
          import android.util.*;
          
          public class SequentialObjectOutputStream extends DataOutputStream
          implements ObjectOutput
          {
              interface FieldGetAction
              {
                  void get(Object obj, Field field) throws IllegalAccessException, IOException;
              }
          
              interface ArrayGetAction
              {
                  void get(Object array, int Index) throws ArrayIndexOutOfBoundsException, IOException;       
              }
          
              public HashMap<Class, FieldGetAction> Primatives;
              public HashMap<Class, ArrayGetAction> ArrayPrimatives;
          
              public SequentialObjectOutputStream(OutputStream stream)
              {
                  super(stream);
          
                  Primatives = new HashMap<Class, FieldGetAction>();
          
                  try
                  {
                      Primatives.put(boolean.class,
                      new FieldGetAction()
                      {
                          public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                          {
                              boolean x = field.getBoolean(obj);
                              writeBoolean(x);
          
                          }
                      });
          
                      Primatives.put(byte.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  byte x = field.getByte(obj);
                                  writeByte(x);
          
                              }
                          });
          
          
                      Primatives.put(short.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  short x = field.getShort(obj);
                                  writeShort(x);
          
                              }
                          });
          
          
                      Primatives.put(int.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  int x = field.getInt(obj);
                                  writeInt(x);
          
                              }
                          });
          
          
                      Primatives.put(long.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  long x = field.getLong(obj);
                                  writeLong(x);
          
                              }
                          });
          
          
                      Primatives.put(char.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  char x = field.getChar(obj);
                                  writeChar(x);
          
                              }
                          });
          
          
                      Primatives.put(float.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  float x = field.getFloat(obj);
                                  writeFloat(x);
          
                              }
                          });
          
          
                      Primatives.put(double.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  double x = field.getDouble(obj);
                                  writeDouble(x);
                              }
                          });
          
          
                      Primatives.put(String.class,
                          new FieldGetAction()
                          {
                              public void get(Object obj, Field field) throws IllegalAccessException, IOException 
                              {
                                  String x = (String) field.get(obj);
                                  writeUTF(x);
          
                              }
                          });
                  } catch(Exception e)
                  {
                      Log.e("SOb", Log.getStackTraceString(e));
                  }
          
          
          
                  ArrayPrimatives = new HashMap<Class, ArrayGetAction>();
          
                  try
                  {
                      ArrayPrimatives.put(boolean.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  boolean x = Array.getBoolean(obj, index);
                                  writeBoolean(x);
          
                              }
                          });
          
                      ArrayPrimatives.put(byte.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  byte x = Array.getByte(obj, index);
                                  writeByte(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(short.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  short x = Array.getShort(obj, index);
                                  writeShort(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(int.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  int x = Array.getInt(obj, index);
                                  writeInt(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(long.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  long x = Array.getLong(obj, index);
                                  writeLong(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(char.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  char x = Array.getChar(obj, index);
                                  writeChar(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(float.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  float x = Array.getFloat(obj, index);
                                  writeFloat(x);
          
                              }
                          });
          
          
                      ArrayPrimatives.put(double.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  double x = Array.getDouble(obj, index);
                                  writeDouble(x);
                              }
                          });
          
          
                      ArrayPrimatives.put(String.class,
                          new ArrayGetAction()
                          {
                              public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException   
                              {
                                  String x = (String) Array.get(obj, index);
                                  writeUTF(x);
          
                              }
                          });
                  } catch(Exception e)
                  {
                      Log.e("SOb", Log.getStackTraceString(e));
                  }
          
              }
          
              class State
              {
                  public ArrayList<Object> OStack = new ArrayList<Object>();
          
                  public long currentId = 1;
          
                  public HashMap<Object, Long> References = new HashMap<Object, Long>();
          
              }
          
              public void writeObject(Object A) throws IOException, NotSerializableException
              {
                  final State state = new State();
          
                  state.OStack.add(0, A);
          
                  LinkedList<Object> ForStack = new LinkedList<Object>();
          
                  while (!(state.OStack.size() == 0))
                  {
                      Object Current = state.OStack.get(0);
                      state.OStack.remove(0);
          
                      if (((Serializable) Current) == null)
                      {
                          throw new NotSerializableException();
                      }
          
          
                      //Type C = Current.getClass();
          
                      Class C = Current.getClass();
          
                      Log.i("SOb", "placing #"+Long.toString(state.currentId)+" of "+C.getCanonicalName()+" on graph"); 
                      state.References.put(Current, state.currentId);
                      state.currentId++;
          
                      ForStack.add(Current);
          
                      if (C.isArray())
                      {
                          //Array array = (Array) Current;
                          Class Ctype = C.getComponentType();
          
                          if (ArrayPrimatives.keySet().contains(Ctype) == false)
                          {
                              for (int I=0; I<Array.getLength(Current); I++)
                              {
                                  Object o = Array.get(Current, I);
          
                                  if ((o != null) && (state.References.keySet().contains(o) == false))
                                  {
                                      if (state.OStack.contains(o) == false) state.OStack.add(state.OStack.size(), o);
                                  }
          
                              }
                          }
                      } else
                      {
                          for (Class Cur = C; Cur != null; Cur = Cur.getSuperclass())
                          {
          
                              Field[] fields = Cur.getDeclaredFields();
          
                              for (Field f : fields)
                              {
                                  if (Modifier.isStatic(f.getModifiers()))
                                  {
                                      continue;
                                  }
          
                                  f.setAccessible(true);
          
                                  if (f.isAccessible() == false)
                                  {
                                  //  Log.i("SOb", "     isAccessible = false");
                                      continue;
                                  }
          
                                  Class type = f.getType();
                                  //Log.i("SOb", "     field \""+f.getName()+"\" of "+type.getCanonicalName());
          
                                  if (Primatives.keySet().contains(type) == false)
                                  {       
                                      try
                                      {
                                          Object o = f.get(Current);
          
                                          if ((o != null) && (state.References.keySet().contains(o) == false))
                                          {
                                              if (state.OStack.contains(o) == false) state.OStack.add(state.OStack.size(), o);
                                          }
          
                                      } catch (IllegalAccessException e)
                                      {
                                          Log.e("SOb", Log.getStackTraceString(e));
                                      }
                                  }
                              }
                          }
                      }
                  }
          
                  writeLong(state.References.size());
          
                  for (Object O : ForStack )
                  {
                      Serializable s = (Serializable) O;
          
                  //  if (s != null)
                      {
                          Class cl = O.getClass();
          
                          String name = cl.getName();
          
                          writeUTF(name);
          
                          if (cl.isArray())
                          {
                              Class components = cl.getComponentType();
          
                              ArrayGetAction action;
          
                              //Array array = (Array) O;
          
                              if (ArrayPrimatives.keySet().contains(components))
                              {
                                  action = ArrayPrimatives.get(components);
                              } else
                              {
                                  action = new ArrayGetAction()
                                  {
                                      public void get(Object array, int index) throws ArrayIndexOutOfBoundsException, IOException     
                                      {
                                          Object O = Array.get(array, index);
                                          if (O==null)  writeLong(0);
                                          else writeLong(state.References.get(O));
                                      }
                                  };
                              }
          
                              int length = Array.getLength(O);
          
                              writeInt(length);
          
                              for (int I=0; I<length; I++)
                              {
                                  action.get(O, I);
                              }
          
                          } else
                          {
                              for (Class Cur = cl; Cur != null; Cur = Cur.getSuperclass())
                              {
                                  Field[] fields = Cur.getDeclaredFields();
          
                                  for (Field F : fields)
                                  {
                                      Class FieldType = F.getType();
          
                                      F.setAccessible(true);
          
                                      if (F.isAccessible() && (Modifier.isStatic(FieldType.getModifiers())))
                                      {
                                          FieldGetAction action;
          
                                          //Array array = (Array) O;
          
                                          if (Primatives.keySet().contains(FieldType))
                                          {
                                              action = Primatives.get(FieldType);
                                          } else
                                          {
                                              action = new FieldGetAction()
                                              {
                                                  public void get(Object obj, Field index) throws IllegalAccessException, IOException     
                                                  {
                                                      Object O = index.get(obj);
                                                      if (O==null)  writeLong(0);
                                                      else writeLong(state.References.get(O));
                                                  }
                                              };
                                          }
          
                                          try
                                          {
                                              action.get(O, F);
                                          } catch (IllegalAccessException e)
                                          {
                                              Log.e("SOb", Log.getStackTraceString(e));
                                          }
          
                                      }
                                  }
          
                              }
                          }
                      }   
                  }
              }
          }
          

          【讨论】:

          • 那是很多代码,没有解释它是如何回答这个问题的。你能补充一下它在做什么吗?
          • 在序列化时,使用 2 遍。第一个将每个唯一对象添加到对象列表中,并为每个对象创建一个索引。第二关。序列化对象的平面视图,使用索引代替字段或数组值的值。这样,在处理对象列表时,序列化对象及其引用就会有一个平面映射,而无需使用递归 writeObject。
          【解决方案7】:

          我遇到了类似的问题。经过多次狩猎,我发现了一个 Kryo 的叉子,用于处理深度嵌套的对象。通过 https://github.com/EsotericSoftware/kryo/issues/103 ,克隆和 mvn clean install https://github.com/romix/kryo/tree/kryo-2.23-continuations 。目前是com.esotericsoftware.kryo:kryo:2.23-SNAPSHOT。

          【讨论】:

            【解决方案8】:

            使用更大的堆栈运行 java

            【讨论】:

            • 这几乎不是解决方案。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多