【问题标题】:De-serializing a graph generates an exception in Java反序列化图形会在 Java 中生成异常
【发布时间】:2026-01-29 22:35:01
【问题描述】:

我创建了一个由节点和边组成的图,如下所示:

public class Edge implements Serializable {
    private final Node neighbor;
    private final double weight;

    public Edge(Node neighbor, double weight) {
        this.neighbor = neighbor;
        this.weight = weight;
    }

    public Node getNeighbor() {
        return neighbor;
    }

    public double getWeight() {
        return weight;
    }
}

public class Node implements Serializable {
    private final String name;
    private final ArrayList<Edge> edges;

    public Node(String name) {
        this.name = name;
        this.edges = new ArrayList<>();
    }

    public String getName() {
        return name;
    }

    public ArrayList<Edge> getEdges() {
        return edges;
    }

    public void addEdge(Edge edge) {
        this.edges.add(edge);
    }
}

public class Graph implements Serializable {
    private final ArrayList<Node> nodes;

    public Graph() {
        nodes = new ArrayList<>();
    }

    public Graph(ArrayList<Node> nodes) {
        this.nodes = nodes;
    }

    public ArrayList<Node> getNodes() {
        return new ArrayList<>(nodes);
    }
}

我正在尝试像这样序列化和反序列化图表:

    public Graph deSerialize() {
        Graph graph = new Graph();
        try {
            FileInputStream inStream = new FileInputStream(aFile);
            ObjectInputStream oIS = new ObjectInputStream(inStream);
            graph = (Graph) oIS.readObject();
            oIS.close();
            inStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return graph;
    }

    private void serialize(Graph graph) {
        try {
            FileOutputStream outStream = new FileOutputStream(aFile);
            ObjectOutputStream oOS = new ObjectOutputStream(outStream);
            oOS.writeObject(graph);
            oOS.close();
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

序列化工作正常(据我所知),但在反序列化过程中打印了以下 StackTrace,我无法弄清楚是什么原因造成的: [更新]:(在序列化时发生)

Exception in thread "main" java.lang.*Error
    at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
    at java.base/java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:339)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1135)
    at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
    at java.base/java.util.ArrayList.writeObject(ArrayList.java:897)
    at java.base/jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)

[添加]:(反序列化时发生)

Exception in thread "main" java.lang.*Error
    at java.base/java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:3169)
    at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1847)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2169)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679)
    at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2464)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2358)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2196)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
    at java.base/java.util.ArrayList.readObject(ArrayList.java:929)
    at java.base/jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)

我尝试了一些不同的方法,包括序列化节点本身的 ArrayList 等,但我无法深入了解它。 有人可以帮我解决这个问题吗?谢谢!

【问题讨论】:

  • 您能添加您的catch 语句吗? oOS.close(); 位于如果序列化确实引发错误时不会被调用的位置。
  • 正是为什么你应该使用 try-with-resources,它是专门为这种情况而开发的。
  • 我确实有,只是没有在此处添加。抱歉......我该如何编辑这个问题?我是 * 的新手!完毕。感谢您的帮助!
  • 在你帖子的最后,在你名字的左边,有一系列链接“分享编辑关注”等。它是编辑。
  • 请不要通过破坏您的帖子为他人增加工作量。通过在 Stack Exchange 网络上发帖,您已在 CC BY-SA 4.0 license 下授予 Stack Exchange 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 Stack Exchange 政策,帖子的非破坏版本是分发的版本。因此,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请参阅:How does deleting work?

标签: java object exception arraylist serialization


【解决方案1】:

“它做到了。”

也许这不是很有帮助。

当您序列化Node 时,Edges 将被递归序列化。 Edge 包含 Node 以便递归序列化。即使是可以导致公平递归深度的适度图,并且每个递归级别都会占用相当大的堆栈空间块。

链表是这个错误的典型例子。标准技术是对整个图形使用自定义序列形式。例如,无论何时遇到Edge,您都可以给它一个序列号(在Map&lt;Edge,Node&gt; 中跟踪。将Nodes 序列化为edgestransient,后跟一组Edge id。依次使用Edge 对象。反序列化时,将Edges 添加回Nodes。

【讨论】: