How can i keep reference to an object that i'm sure it'll be serialized but i don't want it to be serialized through this reference ?
To make it more clear i've a Network
that contains list of Nodes
each Node
contains a list of Connections
, the Connection
contains a reference to another Nodes
.
The problem is when i try serializing kind of big Network
this results to StackOverflowError
, the situation that i'm assuming that causes this is the following:
Network
and tries to serialize the first Node
Node
and so on, and the serialization recursion goes through all nodes causing the overflowConnection
are marked as transient
there is no problem in serialization, but then the references = null
after deserializationHere is a sample that reproduces the problem
Network.java
import java.io.Serializable;
import java.util.ArrayList;
public class Network implements Serializable {
private static final long serialVersionUID = 1399116563470735156L;
ArrayList<Layer>layers;
public Network() {
layers= new ArrayList<Layer>();
}
//connect each layer to next layer
public void connectAllLayers(){
for (int i = 0; i < layers.size()-1; i++) {
layers.get(i).connectTo(layers.get(i+1));
}
}
}
Layer.java
import java.io.Serializable;
import java.util.ArrayList;
public class Layer implements Serializable{
private static final long serialVersionUID = -5519150448729707106L;
public ArrayList<Node>nodes;
public Layer(int nodeCount) {
nodes = new ArrayList<Node>();
for (int i = 0; i < nodeCount; i++) {
nodes.add(new Node());
}
}
//connect all nodes in a layer to all nodes in the other layer
public void connectTo(Layer layer){
for (Node myNode : nodes) {
for (Node toNode : nodes) {
myNode.connectTo(toNode);
}
}
}
}
Node.java
import java.io.Serializable;
import java.util.ArrayList;
public class Node implements Serializable{
private static final long serialVersionUID = 6323513316304801012L;
public ArrayList<Connection>connections;
public double x,y,z,a,b,c;//some variables to simulate memory usage
public Node() {
connections = new ArrayList<Connection>();
x=15;
}
public void connectTo(Node node){
Connection connection = new Connection(this, node);
this.connections.add(connection);
node.connections.add(connection);
}
}
Connection.java
import java.io.Serializable;
public class Connection implements Serializable {
private static final long serialVersionUID = 7578299749680304407L;
public Node from;
public Node to;
public double weight;
public Connection(Node from, Node to) {
this.from = from;
this.to = to;
}
}
Main.java
import java.io.*;
public class Main {
public static void saveNetwork(Network net, String filename) {
try {
// Serialize data object to a file
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream(filename));
out.writeObject(net);
out.close();
} catch (IOException e) {
}
}
public static Network loadNetwork(String filename) {
Network net = null;
try {
FileInputStream door = new FileInputStream(filename);
ObjectInputStream reader = new ObjectInputStream(door);
net = (Network) reader.readObject();
reader.close();
} catch (Exception e) {
System.err.println(e.getMessage());
}
return net;
}
public static void main(String[] args) {
Network net;
boolean load = false;//Change to true to load the saved object
if (!load) {
net = new Network();
net.layers.add(new Layer(400));
net.layers.add(new Layer(300));
net.layers.add(new Layer(10));
net.connectAllLayers();
saveNetwork(net, "mynet");
} else {
net = loadNetwork("mynet");
}
Layer layer = net.layers.get(0);
Node node = layer.nodes.get(0);
Connection connection = node.connections.get(0);
System.out.println(connection.to.x);
}
}
To make the question more general, is there someway to serialize Graph like connected Node classes assuming there is a list that contains references to all Nodes, without causing overflow ?
Java will serialize graphs fine, storing only references to objects that were already serialized. However, it does use recursion in a depth-first fashion, and your graph is very deep (548 nodes deep before I got a stack overflow).
Sort your layers by depth, and serialize them in descending order of depth. This will prevent deep recursion during serialization.