views:

309

answers:

6

I've tried using the standard serializing type things, stuff like:

 FileOutputStream f_out;
try {
 f_out = new FileOutputStream("MAOS.data");
  ObjectOutputStream  obj_out = new ObjectOutputStream (f_out);   
  obj_out.writeObject(s);
     obj_out.flush();
  obj_out.close();

} catch (FileNotFoundException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
} catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
} ;

But the problem seems to be that if my object s contains any recursion at ALL I get a stack overflow. If s is a graph that contains nodes and edges (with nodes knowing about edges for purposes of spreading activation, and edges knowing about nodes for the same reason) then it stack overflows. If I take edges out entirely, and just have nodes that know about which nodes they're supposed to spread activation too, the same thing happens! I can even just try to save the ArrayList of nodes that the graph knows about, and the stack overflows again!

I'm so frustrated!

Graphs aren't exactly strange and mysterious, surely SOMEONE has wanted to save one before me. I'm seeing something about saving them as XML files here...but if my problem is the recursiveness, wouldn't I still be having the same problems even if I saved it differently? I just can't think of how you could make a graph without there being connections!

Am I just doing things wrong, or is this object serialization less powerful than I thought? Or do I need to just abandon the idea of saving a graph?

-Jenny

Edit, part of the HUGE stack trace:

Exception in thread "main" java.lang.StackOverflowError
    at java.io.ObjectStreamClass.getPrimFieldValues(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
A: 

Hmmm. One solution would be to make it into a java bean and use XMLEncoder/XMLDecoder. This is a solution I've used in the past to save and load classes.

Brian
What magic do you think XMLEncoder has?
Tom Hawtin - tackline
In my experience, it does some sort of linking when it encounters things it recognizes. Whether this magic will take place for graphs I don't know, but I've had things go wrong (and right) in the past as a result.
Brian
Also, XMLEncoder gives slightly more helpful error messages than Serialization.
Brian
I'd prefer not to mess around with java bean. I've definitely never been exposed to the technology, and was TRYING to just make a quick little graph in java. I'm seriously considering using Ruby now ^_^;;
Jenny
You cannot program in Java and "never be exposed to the technology" of Java Beans.
foljs
Sort of like how you can't code in rails without coding in Ruby?But what I mean was I'd never heard the term "java bean" before. Therefore, I don't know the first thing about it. If I don't even know what it is, I consider myself not being exposed to it, even if it is just java.
Jenny
I learned just enough about Java Beans to get XMLEncoder to work for a project previously. It took less than a day. Assuming XMLEncoder is a valid solution, lack of knowledge about Java Beans is a poor excuse for avoiding it. Basically, you need a get and set method for everything in your class (and a get and set method for everything in them, etc.) except primitives, such that you could, in theory, clone a class by making a new one with the default constructor and calling `instancecopy.setITEM(instanceoriginal.getITEM());` on all items. All such ITEMs must be primitives or Java Beans.
Brian
A: 

Java serialisation can cope with arbitrary graphs (although not necessarily very efficiently). Probably the problem lies with a custom implementation of writeObject. Perhaps a section of stack trace might help.

Tom Hawtin - tackline
The stack trace is HUGE ^_^;; I'm not really sure what if anything is important about it..so i posted the first part (it's thousands of lines long).. My issue is that nothing I've tried has changed the error, save just creating nodes in a vacuum, storing them in an array, and then not making them a graph.Exception in thread "main" java.lang.StackOverflowError at java.io.ObjectStreamClass.getPrimFieldValues(Unknown Source) at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)tream.t
Jenny
I posted more of the stack trace up top. But... Um. I can assure you I didn't make a custom implementation of writeObject ^_^;; For serious, I have only three classes for this thing.
Jenny
Have you tried a small graph? It looks like it is writing a graph with a large degree of nesting.
Tom Hawtin - tackline
VERY small graphs don't stack overflow, but it seems to not need to get very large before it explodes. My issue is that I'm expecting to deal with VERY large graphs, so I NEED it to work for this ^_^;;
Jenny
So either go for a custom writeObject, along the lines of AbstractList, or hack around to prevent so much recursion (by making sure objects are reached first by less deeply nested recursion).
Tom Hawtin - tackline
+1  A: 

These sort of structures are best saved like this:

collection of nodes, each node has a unique ID
collection of edges, each edge has two node IDs (or however many nodes an edge connects to)

without using any recursion. On reading the nodes, create a dictionary of nodes indexed by their ID. Then use the dictionary to fix up the edges when they're read. The IDs do not need to be part of the objects' run time structure, they only need to be unique within the data stream when the stream is written/read.

Skizz

Skizz
Hmm....that's a really good idea. My only concern is, won't that really affect run time, if I have by graph searching through all nodes and edges every time anything needs done? Right now it's an arraylist, which to find a node with a specific id I would have to iterate through the whole thing, worst case scenario i'm going though every node (or edge), which could be hundreds of thousands! Are has tables any faster?
Jenny
*hash tables, I meant.
Jenny
Yes, they are O(1)
foljs
A: 

A useful serialization format you should consider is JSON, where dictionaries (as suggested by @Skizz) are easily represented:

A JSONObject is an unordered collection of name/value pairs. Its external form is a string wrapped in curly braces with colons between the names and values, and commas between the values and names. The internal form is an object having get() and opt() methods for accessing the values by name, and put() methods for adding or replacing values by name. The values can be any of these types: Boolean, JSONArray, JSONObject, Number, and String, or the JSONObject.NULL object.

gimel
You will still have deep nesting. Not sure how well JSON handles arbitrary graphs.
Tom Hawtin - tackline
build the graph from 2 collections (not a recursive object), as suggested by @Skizz. Each collection is easily serialized with JSON.
gimel
+1  A: 

You could use the JGraphT library which supports serializing graphs into a text file with the ML format. GraphMLExporter Javadoc.

willcodejavaforfood
A: 

Java serialization is capable of handling cyclic references (I assume this is what you mean by recursion), but there is a known problem with large graphs that is described here.

Don't let the date of the article throw you off, just follow chain of comments after it.

It seems you will have to use another serialization technique to accomplish this. Several have been mentioned, and some performance metrics give JSON high marks.

Robin